feat: init video presentation agent

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-03-21 22:13:41 -07:00
parent 40d949b7d5
commit b28f135a96
37 changed files with 3567 additions and 24 deletions

View file

@ -103,6 +103,13 @@ class PodcastStatus(StrEnum):
FAILED = "failed"
class VideoPresentationStatus(StrEnum):
PENDING = "pending"
GENERATING = "generating"
READY = "ready"
FAILED = "failed"
class DocumentStatus:
"""
Helper class for document processing status (stored as JSONB).
@ -337,6 +344,12 @@ class Permission(StrEnum):
PODCASTS_UPDATE = "podcasts:update"
PODCASTS_DELETE = "podcasts:delete"
# Video Presentations
VIDEO_PRESENTATIONS_CREATE = "video_presentations:create"
VIDEO_PRESENTATIONS_READ = "video_presentations:read"
VIDEO_PRESENTATIONS_UPDATE = "video_presentations:update"
VIDEO_PRESENTATIONS_DELETE = "video_presentations:delete"
# Image Generations
IMAGE_GENERATIONS_CREATE = "image_generations:create"
IMAGE_GENERATIONS_READ = "image_generations:read"
@ -403,6 +416,10 @@ DEFAULT_ROLE_PERMISSIONS = {
Permission.PODCASTS_CREATE.value,
Permission.PODCASTS_READ.value,
Permission.PODCASTS_UPDATE.value,
# Video Presentations (no delete)
Permission.VIDEO_PRESENTATIONS_CREATE.value,
Permission.VIDEO_PRESENTATIONS_READ.value,
Permission.VIDEO_PRESENTATIONS_UPDATE.value,
# Image Generations (create and read, no delete)
Permission.IMAGE_GENERATIONS_CREATE.value,
Permission.IMAGE_GENERATIONS_READ.value,
@ -435,6 +452,8 @@ DEFAULT_ROLE_PERMISSIONS = {
Permission.LLM_CONFIGS_READ.value,
# Podcasts (read only)
Permission.PODCASTS_READ.value,
# Video Presentations (read only)
Permission.VIDEO_PRESENTATIONS_READ.value,
# Image Generations (read only)
Permission.IMAGE_GENERATIONS_READ.value,
# Connectors (read only)
@ -1044,6 +1063,46 @@ class Podcast(BaseModel, TimestampMixin):
thread = relationship("NewChatThread")
class VideoPresentation(BaseModel, TimestampMixin):
"""Video presentation model for storing AI-generated video presentations.
The slides JSONB stores per-slide data including Remotion component code,
audio file paths, and durations. The frontend compiles the code and renders
the video using Remotion Player.
"""
__tablename__ = "video_presentations"
title = Column(String(500), nullable=False)
slides = Column(JSONB, nullable=True)
scene_codes = Column(JSONB, nullable=True)
status = Column(
SQLAlchemyEnum(
VideoPresentationStatus,
name="video_presentation_status",
create_type=False,
values_callable=lambda x: [e.value for e in x],
),
nullable=False,
default=VideoPresentationStatus.READY,
server_default="ready",
index=True,
)
search_space_id = Column(
Integer, ForeignKey("searchspaces.id", ondelete="CASCADE"), nullable=False
)
search_space = relationship("SearchSpace", back_populates="video_presentations")
thread_id = Column(
Integer,
ForeignKey("new_chat_threads.id", ondelete="SET NULL"),
nullable=True,
index=True,
)
thread = relationship("NewChatThread")
class Report(BaseModel, TimestampMixin):
"""Report model for storing generated Markdown reports."""
@ -1228,6 +1287,12 @@ class SearchSpace(BaseModel, TimestampMixin):
order_by="Podcast.id.desc()",
cascade="all, delete-orphan",
)
video_presentations = relationship(
"VideoPresentation",
back_populates="search_space",
order_by="VideoPresentation.id.desc()",
cascade="all, delete-orphan",
)
reports = relationship(
"Report",
back_populates="search_space",