Spaces:
Runtime error
Runtime error
Download backend/app/models/content.py from firebird-technologies/NoteStack-Test: direct link, hf CLI and curl.
- Browser
- Download file 19.8 kB
-
https://huggingface.co/spaces/firebird-technologies/NoteStack-Test/resolve/1aa4a1663ff037b16e33cea96515f0268a23545d/backend/app/models/content.py
- Command line
-
hf download hf://spaces/firebird-technologies/NoteStack-Test@1aa4a1663ff037b16e33cea96515f0268a23545d/backend/app/models/content.py
-
curl -L -o content.py https://huggingface.co/spaces/firebird-technologies/NoteStack-Test/resolve/1aa4a1663ff037b16e33cea96515f0268a23545d/backend/app/models/content.py
19.8 kB
| import uuid | |
| from datetime import datetime | |
| from sqlalchemy import ( | |
| JSON, | |
| BigInteger, | |
| Boolean, | |
| DateTime, | |
| Float, | |
| ForeignKey, | |
| Index, | |
| Integer, | |
| String, | |
| Text, | |
| UniqueConstraint, | |
| Uuid, | |
| text, | |
| ) | |
| from sqlalchemy.orm import Mapped, mapped_column, relationship | |
| from app.db import Base | |
| from app.models.base import IdMixin, TimestampMixin | |
| def _ws_fk() -> Mapped[uuid.UUID]: | |
| return mapped_column(Uuid, ForeignKey("workspaces.id", ondelete="CASCADE"), index=True) | |
| class Source(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "sources" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| feed_url: Mapped[str] = mapped_column(String(1000)) | |
| site_url: Mapped[str | None] = mapped_column(String(1000)) | |
| platform: Mapped[str] = mapped_column(String(20), default="rss") # substack | ghost | medium | rss | url | |
| title: Mapped[str | None] = mapped_column(String(500)) | |
| sync_status: Mapped[str] = mapped_column(String(20), default="pending") # pending | syncing | ok | error | |
| sync_error: Mapped[str | None] = mapped_column(Text) | |
| last_synced_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| class Document(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "documents" | |
| __table_args__ = (UniqueConstraint("source_id", "url"),) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| source_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("sources.id", ondelete="CASCADE")) | |
| title: Mapped[str] = mapped_column(String(1000)) | |
| url: Mapped[str] = mapped_column(String(1000)) | |
| published_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| raw_html_key: Mapped[str | None] = mapped_column(String(500)) # R2 key | |
| # Corpus relative path of the clean markdown file, e.g. sources/ada-substack-com/2026-03-01-pricing.md | |
| path: Mapped[str | None] = mapped_column(String(500), index=True) | |
| clean_text: Mapped[str] = mapped_column(Text, default="") | |
| content_hash: Mapped[str | None] = mapped_column(String(64)) | |
| metadata_json: Mapped[dict] = mapped_column(JSON, default=dict) | |
| # Resurfacing: 0..1 from the EvergreenScore module (reason and angle live in metadata_json) | |
| evergreen_score: Mapped[float | None] = mapped_column(Float) | |
| last_resurfaced_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| class Notebook(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "notebooks" | |
| # One "All posts" notebook per workspace: two requests opening it at once cannot both create one. | |
| __table_args__ = (Index("uq_notebooks_one_archive", "workspace_id", unique=True, | |
| postgresql_where=text("is_archive"), sqlite_where=text("is_archive")),) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| title: Mapped[str] = mapped_column(String(300)) | |
| description: Mapped[str | None] = mapped_column(Text) | |
| summary: Mapped[str | None] = mapped_column(Text) | |
| # The workspace's "All posts" notebook: created on demand, kept in step with every indexed post. | |
| is_archive: Mapped[bool] = mapped_column(Boolean, default=False) | |
| class NotebookDocument(Base): | |
| __tablename__ = "notebook_documents" | |
| notebook_id: Mapped[uuid.UUID] = mapped_column( | |
| Uuid, ForeignKey("notebooks.id", ondelete="CASCADE"), primary_key=True | |
| ) | |
| document_id: Mapped[uuid.UUID] = mapped_column( | |
| Uuid, ForeignKey("documents.id", ondelete="CASCADE"), primary_key=True | |
| ) | |
| class VoiceProfile(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "voice_profiles" | |
| workspace_id: Mapped[uuid.UUID] = mapped_column( | |
| Uuid, ForeignKey("workspaces.id", ondelete="CASCADE"), unique=True | |
| ) | |
| profile_json: Mapped[dict] = mapped_column(JSON, default=dict) | |
| sample_doc_ids: Mapped[list] = mapped_column(JSON, default=list) | |
| host_voices: Mapped[dict] = mapped_column(JSON, default=dict) # {"host_a": voice_id, "host_b": voice_id} | |
| class VoiceConsent(IdMixin, TimestampMixin, Base): | |
| """Required before any voice cloning. The recorded sample lives in R2.""" | |
| __tablename__ = "voice_consents" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| user_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("users.id")) | |
| sample_key: Mapped[str] = mapped_column(String(500)) | |
| consent_text: Mapped[str] = mapped_column(Text) | |
| ip_address: Mapped[str | None] = mapped_column(String(64)) | |
| elevenlabs_voice_id: Mapped[str | None] = mapped_column(String(100)) | |
| revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| class Chat(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "chats" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| notebook_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("notebooks.id", ondelete="CASCADE")) | |
| title: Mapped[str | None] = mapped_column(String(300)) | |
| class Message(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "messages" | |
| chat_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("chats.id", ondelete="CASCADE"), index=True) | |
| role: Mapped[str] = mapped_column(String(20)) # user | assistant | |
| content: Mapped[str] = mapped_column(Text) | |
| citations: Mapped[list["Citation"]] = relationship(cascade="all, delete-orphan") | |
| class Citation(IdMixin, Base): | |
| __tablename__ = "citations" | |
| message_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("messages.id", ondelete="CASCADE")) | |
| document_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("documents.id", ondelete="CASCADE")) | |
| marker: Mapped[int] = mapped_column(Integer) # [1], [2] in the answer text | |
| path: Mapped[str] = mapped_column(String(500)) | |
| line_start: Mapped[int] = mapped_column(Integer) | |
| line_end: Mapped[int] = mapped_column(Integer) | |
| span: Mapped[str | None] = mapped_column(Text) # verified text read back from the file | |
| class Artifact(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "artifacts" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| notebook_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("notebooks.id", ondelete="SET NULL")) | |
| document_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("documents.id", ondelete="SET NULL")) | |
| # summary | audio_overview | video | thread | linkedin | notes | quote_card | carousel | seo | |
| type: Mapped[str] = mapped_column(String(30)) | |
| # pending | generating | ready | failed | rendering | review; a video also takes blog2video's job statuses as they | |
| # are: regenerating (template switch) | voice_regenerating | language_regenerating | script_regenerating | |
| status: Mapped[str] = mapped_column(String(40), default="pending") | |
| content_json: Mapped[dict] = mapped_column(JSON, default=dict) | |
| storage_key: Mapped[str | None] = mapped_column(String(500)) | |
| class B2VVideo(IdMixin, TimestampMixin, Base): | |
| """One blog2video video we asked for: the only place its blog2video id lives. Every read, edit and delete on | |
| blog2video goes through this row (b2v_video_id, and created_via for the right endpoints). Also records who made it | |
| and whether the workspace's video allowance is still charged for it. | |
| Our API key reaches every video it created, for every workspace, so this table (with the artifact) is what | |
| ties a blog2video id to one workspace. quota_state moves charged -> refunded (or -> kept once generated), with a | |
| conditional UPDATE (see video_quota.refund), so the status poller and the sweep can not refund twice.""" | |
| __tablename__ = "b2v_videos" | |
| __table_args__ = (Index("ix_b2v_videos_ws_created", "workspace_id", "created_at"),) | |
| workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("workspaces.id", ondelete="CASCADE")) | |
| user_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("users.id", ondelete="SET NULL"), | |
| index=True) # who made it | |
| artifact_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("artifacts.id", ondelete="SET NULL"), | |
| index=True) | |
| # blog2video's video id, which is also its project id. Null until blog2video accepts the create. | |
| b2v_video_id: Mapped[int | None] = mapped_column(Integer, unique=True) | |
| idempotency_key: Mapped[str | None] = mapped_column(String(100), unique=True) # "<workspace_id>:<uuid>"; v1 only | |
| created_via: Mapped[str] = mapped_column(String(10), default="v1", server_default="v1") # v1 | upload | |
| template_ref: Mapped[str | None] = mapped_column(String(100)) # e.g. custom_58: blocks deleting that template | |
| title: Mapped[str | None] = mapped_column(String(300)) | |
| source_url: Mapped[str | None] = mapped_column(String(2000)) # the link it was made from (null for files, text) | |
| aspect_ratio: Mapped[str | None] = mapped_column(String(20)) | |
| preview_url: Mapped[str | None] = mapped_column(String(1000)) # public live preview (embed token) | |
| video_url: Mapped[str | None] = mapped_column(String(1000)) # the rendered MP4 | |
| quota_state: Mapped[str] = mapped_column(String(20), default="charged") # charged | refunded | kept | |
| status: Mapped[str] = mapped_column(String(40), default="queued") # last known blog2video status | |
| class B2VTemplate(TimestampMixin, Base): | |
| """A custom template this workspace made. Used on videos as custom_<b2v_template_id>; only when ready.""" | |
| __tablename__ = "b2v_templates" | |
| b2v_template_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=False) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| name: Mapped[str] = mapped_column(String(255)) | |
| ready: Mapped[bool] = mapped_column(Boolean, default=False) # code generation finished ('complete') | |
| class B2VCustomVoice(TimestampMixin, Base): | |
| """A designed or cloned voice this workspace made. Videos reference it by voice_id (custom_voice_id).""" | |
| __tablename__ = "b2v_custom_voices" | |
| b2v_custom_voice_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=False) # preview/delete | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| voice_id: Mapped[str] = mapped_column(String(100), unique=True) # the ElevenLabs id sent as custom_voice_id | |
| name: Mapped[str] = mapped_column(String(255)) | |
| source: Mapped[str] = mapped_column(String(20)) # prompt | preset | clone | |
| preview_url: Mapped[str | None] = mapped_column(String(1000)) | |
| class UserSavedVoice(TimestampMixin, Base): | |
| """The workspace's "My voices" list. Kept only here: blog2video's saved-voice list is shared by everyone.""" | |
| __tablename__ = "user_saved_voices" | |
| workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("workspaces.id", ondelete="CASCADE"), | |
| primary_key=True) | |
| voice_id: Mapped[str] = mapped_column(String(100), primary_key=True) | |
| name: Mapped[str] = mapped_column(String(255)) | |
| preview_url: Mapped[str | None] = mapped_column(String(1000)) | |
| gender: Mapped[str | None] = mapped_column(String(20)) | |
| accent: Mapped[str | None] = mapped_column(String(50)) | |
| premium: Mapped[bool] = mapped_column(Boolean, default=False) # a paid built-in voice, or any custom voice | |
| is_custom: Mapped[bool] = mapped_column(Boolean, default=False) | |
| class B2VStyle(TimestampMixin, Base): | |
| """A custom video style this workspace made. Used on videos as custom:<b2v_style_id>.""" | |
| __tablename__ = "b2v_styles" | |
| b2v_style_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=False) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| name: Mapped[str] = mapped_column(String(80)) | |
| class UsageCounter(Base): | |
| """Per-workspace counters for the video features blog2video only limits account-wide (video_limits.py).""" | |
| __tablename__ = "usage_counters" | |
| workspace_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("workspaces.id", ondelete="CASCADE"), | |
| primary_key=True) | |
| period: Mapped[str] = mapped_column(String(10), primary_key=True) # 2026-10 | 2026-10-02 | all | |
| metric: Mapped[str] = mapped_column(String(30), primary_key=True) | |
| used: Mapped[int] = mapped_column(Integer, default=0) | |
| class Job(IdMixin, TimestampMixin, Base): | |
| """Covers ingest, tts and render jobs. kind decides which fields matter. | |
| This table is also the queue: workers claim queued rows with FOR UPDATE SKIP LOCKED | |
| (see app/worker.py), so no separate broker is needed. | |
| """ | |
| __tablename__ = "jobs" | |
| __table_args__ = (Index("ix_jobs_queue", "status", "run_after", "created_at"),) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| kind: Mapped[str] = mapped_column(String(30)) # ingest | tts | render | generate | |
| status: Mapped[str] = mapped_column(String(20), default="queued") # queued | running | done | failed | |
| progress: Mapped[float] = mapped_column(Float, default=0.0) | |
| message: Mapped[str | None] = mapped_column(String(500)) | |
| error: Mapped[str | None] = mapped_column(Text) | |
| params: Mapped[dict] = mapped_column(JSON, default=dict) | |
| result: Mapped[dict] = mapped_column(JSON, default=dict) | |
| artifact_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("artifacts.id", ondelete="SET NULL")) | |
| cost_usd: Mapped[float] = mapped_column(Float, default=0.0) | |
| finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| # Queue bookkeeping | |
| attempts: Mapped[int] = mapped_column(Integer, default=0) | |
| max_attempts: Mapped[int] = mapped_column(Integer, default=3) | |
| run_after: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) # retry backoff | |
| locked_by: Mapped[str | None] = mapped_column(String(100)) # worker id while running | |
| heartbeat_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) # stale detection | |
| class Upload(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "uploads" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| user_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("users.id")) | |
| key: Mapped[str] = mapped_column(String(500), unique=True) | |
| filename: Mapped[str] = mapped_column(String(300)) | |
| content_type: Mapped[str] = mapped_column(String(100)) | |
| size_bytes: Mapped[int | None] = mapped_column(BigInteger) | |
| status: Mapped[str] = mapped_column(String(20), default="pending") # pending | complete | |
| class CalendarItem(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "calendar_items" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| artifact_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("artifacts.id", ondelete="CASCADE")) | |
| document_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("documents.id", ondelete="SET NULL")) | |
| platform: Mapped[str] = mapped_column(String(30)) # x | linkedin | bluesky | substack_notes | |
| scheduled_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), index=True) | |
| # scheduled | publishing | posted | reminded | failed | draft | |
| status: Mapped[str] = mapped_column(String(20), default="scheduled") | |
| content: Mapped[str] = mapped_column(Text, default="") | |
| thread: Mapped[list] = mapped_column(JSON, default=list) # extra posts after the first, for threads | |
| social_account_id: Mapped[uuid.UUID | None] = mapped_column( | |
| Uuid, ForeignKey("social_accounts.id", ondelete="SET NULL") | |
| ) | |
| remind_by_email: Mapped[bool] = mapped_column(Boolean, default=False) | |
| external_id: Mapped[str | None] = mapped_column(String(200)) | |
| external_url: Mapped[str | None] = mapped_column(String(1000)) | |
| posted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| error: Mapped[str | None] = mapped_column(Text) | |
| attempts: Mapped[int] = mapped_column(Integer, default=0) | |
| metrics: Mapped[dict] = mapped_column(JSON, default=dict) # likes, reposts, replies, impressions | |
| class SocialAccount(IdMixin, TimestampMixin, Base): | |
| """A connected X, LinkedIn or Bluesky account. Tokens are Fernet encrypted (app/services/crypto.py).""" | |
| __tablename__ = "social_accounts" | |
| __table_args__ = (UniqueConstraint("workspace_id", "platform", "external_id"),) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| platform: Mapped[str] = mapped_column(String(20)) | |
| handle: Mapped[str] = mapped_column(String(200)) | |
| external_id: Mapped[str] = mapped_column(String(200)) | |
| access_token: Mapped[str] = mapped_column(Text) | |
| refresh_token: Mapped[str | None] = mapped_column(Text) | |
| expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) | |
| scopes: Mapped[str | None] = mapped_column(String(500)) | |
| status: Mapped[str] = mapped_column(String(20), default="active") # active | expired | revoked | |
| avatar_url: Mapped[str | None] = mapped_column(String(1000)) | |
| class Topic(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "topics" | |
| __table_args__ = (UniqueConstraint("workspace_id", "slug"),) | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| name: Mapped[str] = mapped_column(String(200)) | |
| slug: Mapped[str] = mapped_column(String(200)) | |
| summary: Mapped[str | None] = mapped_column(Text) | |
| post_count: Mapped[int] = mapped_column(Integer, default=0) | |
| class DocumentTopic(Base): | |
| __tablename__ = "document_topics" | |
| document_id: Mapped[uuid.UUID] = mapped_column( | |
| Uuid, ForeignKey("documents.id", ondelete="CASCADE"), primary_key=True | |
| ) | |
| topic_id: Mapped[uuid.UUID] = mapped_column(Uuid, ForeignKey("topics.id", ondelete="CASCADE"), primary_key=True) | |
| weight: Mapped[float] = mapped_column(Float, default=1.0) | |
| class TrackedLink(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "tracked_links" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| slug: Mapped[str] = mapped_column(String(32), unique=True) | |
| target_url: Mapped[str] = mapped_column(String(2000)) | |
| calendar_item_id: Mapped[uuid.UUID | None] = mapped_column( | |
| Uuid, ForeignKey("calendar_items.id", ondelete="SET NULL") | |
| ) | |
| class EngagementEvent(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "engagement_events" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| tracked_link_id: Mapped[uuid.UUID | None] = mapped_column( | |
| Uuid, ForeignKey("tracked_links.id", ondelete="CASCADE") | |
| ) | |
| kind: Mapped[str] = mapped_column(String(30)) # click | like | repost | reply | subscribe | |
| value: Mapped[float] = mapped_column(Float, default=1.0) | |
| metadata_json: Mapped[dict] = mapped_column(JSON, default=dict) | |
| class DspyTrace(IdMixin, TimestampMixin, Base): | |
| __tablename__ = "dspy_traces" | |
| workspace_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("workspaces.id", ondelete="SET NULL")) | |
| module: Mapped[str] = mapped_column(String(60), index=True) | |
| model: Mapped[str] = mapped_column(String(100)) | |
| inputs: Mapped[dict] = mapped_column(JSON, default=dict) | |
| outputs: Mapped[dict] = mapped_column(JSON, default=dict) | |
| score: Mapped[float | None] = mapped_column(Float) | |
| feedback: Mapped[str | None] = mapped_column(Text) | |
| # Only usable for optimization when the workspace opted in. | |
| training_allowed: Mapped[bool] = mapped_column(Boolean, default=False) | |
| class UsageEvent(IdMixin, TimestampMixin, Base): | |
| """Metering: LLM tokens, TTS characters, render seconds. One row per billable call.""" | |
| __tablename__ = "usage_events" | |
| workspace_id: Mapped[uuid.UUID] = _ws_fk() | |
| job_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, ForeignKey("jobs.id", ondelete="SET NULL")) | |
| kind: Mapped[str] = mapped_column(String(20)) # llm | tts | render | |
| provider: Mapped[str] = mapped_column(String(40)) | |
| model: Mapped[str | None] = mapped_column(String(100)) | |
| quantity: Mapped[float] = mapped_column(Float) # tokens, characters or seconds | |
| unit: Mapped[str] = mapped_column(String(20)) | |
| cost_usd: Mapped[float] = mapped_column(Float, default=0.0) | |