feat(article-discuss): unify /news + briefing entry points, persist summaries to RAG

Both the /news discuss button and the briefing discuss button now call a
shared seed_article_discussion() helper that stages the synthetic
read_article tool exchange and the conversational seed prompt — behavior
stays byte-identical across entry points. /news also auto-starts
generation so the chat screen lands on an in-flight stream.

First assistant reply in a seeded article conversation is persisted as a
Note (tags: article-summary + article topics) and backlinked via
rss_items.discussion_note_id, so the knowledge base stops being amnesiac
about articles the user has engaged with.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-14 07:54:24 -04:00
parent 9157740069
commit ba90ad8132
8 changed files with 284 additions and 78 deletions
+8 -1
View File
@@ -1,6 +1,6 @@
from datetime import datetime, timezone
from sqlalchemy import ARRAY, DateTime, ForeignKey, Index, Integer, Text, UniqueConstraint
from sqlalchemy import ARRAY, BigInteger, DateTime, ForeignKey, Index, Integer, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from fabledassistant.models import Base
@@ -66,6 +66,13 @@ class RssItem(Base):
classified_at: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), nullable=True
)
# Note persisting the first-click discussion summary. Set by the article
# discussion pipeline once the seeded chat completes its first assistant
# reply; links back into RAG so re-discussing the same article lands the
# prior summary in context.
discussion_note_id: Mapped[int | None] = mapped_column(
BigInteger, ForeignKey("notes.id", ondelete="SET NULL"), nullable=True
)
feed: Mapped["RssFeed"] = relationship(back_populates="items")