diff --git a/surfsense_backend/alembic/versions/126_add_report_content_type.py b/surfsense_backend/alembic/versions/126_add_report_content_type.py new file mode 100644 index 000000000..3d9e4860c --- /dev/null +++ b/surfsense_backend/alembic/versions/126_add_report_content_type.py @@ -0,0 +1,42 @@ +"""126_add_report_content_type + +Revision ID: 126 +Revises: 125 +Create Date: 2026-04-15 + +Adds content_type column to reports table to distinguish between +Markdown reports and Typst-based resumes. +""" + +from __future__ import annotations + +from collections.abc import Sequence + +import sqlalchemy as sa + +from alembic import op + +revision: str = "126" +down_revision: str | None = "125" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + conn = op.get_bind() + columns = [c["name"] for c in sa.inspect(conn).get_columns("reports")] + if "content_type" in columns: + return + op.add_column( + "reports", + sa.Column( + "content_type", + sa.String(20), + nullable=False, + server_default="markdown", + ), + ) + + +def downgrade() -> None: + op.drop_column("reports", "content_type") diff --git a/surfsense_backend/alembic/versions/127_seed_build_resume_prompt.py b/surfsense_backend/alembic/versions/127_seed_build_resume_prompt.py new file mode 100644 index 000000000..9e05a0510 --- /dev/null +++ b/surfsense_backend/alembic/versions/127_seed_build_resume_prompt.py @@ -0,0 +1,43 @@ +"""127_seed_build_resume_prompt + +Revision ID: 127 +Revises: 126 +Create Date: 2026-04-15 + +Seeds the 'Build Resume' default prompt for all existing users. +New users get it automatically via SYSTEM_PROMPT_DEFAULTS on signup. +""" + +from __future__ import annotations + +from collections.abc import Sequence + +import sqlalchemy as sa + +from alembic import op + +revision: str = "127" +down_revision: str | None = "126" +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None + + +def upgrade() -> None: + conn = op.get_bind() + conn.execute( + sa.text( + """ + INSERT INTO prompts + (user_id, default_prompt_slug, name, prompt, mode, version, is_public, created_at) + SELECT u.id, 'build-resume', 'Build Resume', + E'Build me a professional resume. Here is my information:\\n\\n{selection}', + 'explore'::prompt_mode, 1, false, now() + FROM "user" u + ON CONFLICT (user_id, default_prompt_slug) DO NOTHING + """ + ) + ) + + +def downgrade() -> None: + op.execute("DELETE FROM prompts WHERE default_prompt_slug = 'build-resume'") diff --git a/surfsense_backend/app/db.py b/surfsense_backend/app/db.py index 61bdd65cb..239f306f5 100644 --- a/surfsense_backend/app/db.py +++ b/surfsense_backend/app/db.py @@ -1191,12 +1191,13 @@ class VideoPresentation(BaseModel, TimestampMixin): class Report(BaseModel, TimestampMixin): - """Report model for storing generated Markdown reports.""" + """Report model for storing generated reports (Markdown or Typst).""" __tablename__ = "reports" title = Column(String(500), nullable=False) - content = Column(Text, nullable=True) # Markdown body + content = Column(Text, nullable=True) + content_type = Column(String(20), nullable=False, server_default="markdown") report_metadata = Column(JSONB, nullable=True) # section headings, word count, etc. report_style = Column( String(100), nullable=True