2026-06-07 22:16:56 +02:00
|
|
|
"""Add prompter_sessions, prompter_messages, and task_drafts tables.
|
|
|
|
|
|
|
|
|
|
Adds three new tables to support the Prompter conversational assistant
|
|
|
|
|
feature with DB-persisted conversation history and task draft tracking:
|
|
|
|
|
|
|
|
|
|
- prompter_sessions: links a conversation session to an authenticated agent
|
|
|
|
|
- prompter_messages: stores the full message history (user + assistant turns)
|
|
|
|
|
- task_drafts: stores structured task drafts extracted from conversations;
|
|
|
|
|
links to a real Task once the human confirms via /confirm endpoint
|
|
|
|
|
|
|
|
|
|
Revision ID: 024_add_prompter_tables
|
2026-06-08 15:06:15 +02:00
|
|
|
Revises: 023_prompter_tracking_columns
|
2026-06-07 22:16:56 +02:00
|
|
|
Create Date: 2026-06-07
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import sqlalchemy as sa
|
|
|
|
|
from alembic import op
|
|
|
|
|
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
|
|
|
|
|
|
|
|
|
revision = "024_add_prompter_tables"
|
2026-06-08 15:06:15 +02:00
|
|
|
down_revision = "023_prompter_tracking_columns"
|
2026-06-07 22:16:56 +02:00
|
|
|
branch_labels = None
|
|
|
|
|
depends_on = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def upgrade() -> None:
|
|
|
|
|
# --- prompter_sessions -----------------------------------------------
|
|
|
|
|
op.create_table(
|
|
|
|
|
"prompter_sessions",
|
|
|
|
|
sa.Column("id", UUID(as_uuid=True), primary_key=True),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"agent_id",
|
|
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
sa.ForeignKey("agents.id", ondelete="CASCADE"),
|
|
|
|
|
nullable=False,
|
|
|
|
|
),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"status",
|
|
|
|
|
sa.Enum(
|
|
|
|
|
"active",
|
|
|
|
|
"draft_ready",
|
|
|
|
|
"confirmed",
|
|
|
|
|
"abandoned",
|
|
|
|
|
name="promptersessionstatus",
|
|
|
|
|
),
|
|
|
|
|
nullable=False,
|
|
|
|
|
server_default="active",
|
|
|
|
|
),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"created_at",
|
|
|
|
|
sa.DateTime(timezone=True),
|
|
|
|
|
nullable=False,
|
|
|
|
|
server_default=sa.func.now(),
|
|
|
|
|
),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"updated_at",
|
|
|
|
|
sa.DateTime(timezone=True),
|
|
|
|
|
nullable=True,
|
|
|
|
|
onupdate=sa.func.now(),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
op.create_index("ix_prompter_sessions_agent_id", "prompter_sessions", ["agent_id"])
|
|
|
|
|
op.create_index(
|
|
|
|
|
"ix_prompter_sessions_status", "prompter_sessions", ["status"]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# --- prompter_messages -----------------------------------------------
|
|
|
|
|
op.create_table(
|
|
|
|
|
"prompter_messages",
|
|
|
|
|
sa.Column("id", UUID(as_uuid=True), primary_key=True),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"session_id",
|
|
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
sa.ForeignKey("prompter_sessions.id", ondelete="CASCADE"),
|
|
|
|
|
nullable=False,
|
|
|
|
|
),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"role",
|
|
|
|
|
sa.Enum("user", "assistant", "system", name="promptermessagerole"),
|
|
|
|
|
nullable=False,
|
|
|
|
|
),
|
|
|
|
|
sa.Column("content", sa.Text, nullable=False),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"created_at",
|
|
|
|
|
sa.DateTime(timezone=True),
|
|
|
|
|
nullable=False,
|
|
|
|
|
server_default=sa.func.now(),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
op.create_index(
|
|
|
|
|
"ix_prompter_messages_session_id", "prompter_messages", ["session_id"]
|
|
|
|
|
)
|
|
|
|
|
op.create_index(
|
|
|
|
|
"ix_prompter_messages_session_created",
|
|
|
|
|
"prompter_messages",
|
|
|
|
|
["session_id", "created_at"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# --- task_drafts -----------------------------------------------------
|
|
|
|
|
op.create_table(
|
|
|
|
|
"task_drafts",
|
|
|
|
|
sa.Column("id", UUID(as_uuid=True), primary_key=True),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"session_id",
|
|
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
sa.ForeignKey("prompter_sessions.id", ondelete="CASCADE"),
|
|
|
|
|
nullable=False,
|
|
|
|
|
),
|
|
|
|
|
sa.Column("draft_data", JSONB, nullable=False),
|
|
|
|
|
sa.Column("confirmed_at", sa.DateTime(timezone=True), nullable=True),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"task_id",
|
|
|
|
|
UUID(as_uuid=True),
|
|
|
|
|
sa.ForeignKey("tasks.id", ondelete="SET NULL"),
|
|
|
|
|
nullable=True,
|
|
|
|
|
),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"created_at",
|
|
|
|
|
sa.DateTime(timezone=True),
|
|
|
|
|
nullable=False,
|
|
|
|
|
server_default=sa.func.now(),
|
|
|
|
|
),
|
|
|
|
|
sa.Column(
|
|
|
|
|
"updated_at",
|
|
|
|
|
sa.DateTime(timezone=True),
|
|
|
|
|
nullable=True,
|
|
|
|
|
onupdate=sa.func.now(),
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
op.create_index("ix_task_drafts_session_id", "task_drafts", ["session_id"])
|
|
|
|
|
op.create_index("ix_task_drafts_task_id", "task_drafts", ["task_id"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def downgrade() -> None:
|
|
|
|
|
op.drop_table("task_drafts")
|
|
|
|
|
op.drop_index("ix_prompter_messages_session_created", "prompter_messages")
|
|
|
|
|
op.drop_index("ix_prompter_messages_session_id", "prompter_messages")
|
|
|
|
|
op.drop_table("prompter_messages")
|
|
|
|
|
op.drop_index("ix_prompter_sessions_status", "prompter_sessions")
|
|
|
|
|
op.drop_index("ix_prompter_sessions_agent_id", "prompter_sessions")
|
|
|
|
|
op.drop_table("prompter_sessions")
|
|
|
|
|
op.execute("DROP TYPE IF EXISTS promptersessionstatus")
|
|
|
|
|
op.execute("DROP TYPE IF EXISTS promptermessagerole")
|