From ef2fabc15859ef622b246c4a98cefc3dc06829f3 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 9 Feb 2026 18:24:19 +0800 Subject: [PATCH] fix: adjustment the migration files --- ..._08_1031-aab323465866_sandbox_providers.py | 56 -------- ...4a64f53_add_llm_generation_detail_table.py | 45 ------- ...a1b2c3d4e5f6_add_app_asset_drafts_table.py | 39 ------ ..._15_1649-d88f3edbd99d_rename_app_assets.py | 68 ---------- ...e916693_sandbox_provider_configure_type.py | 35 ----- ...27822d22895_add_workflow_comments_table.py | 90 ------------- ...c4f34_add_default_sandbox_system_config.py | 67 ---------- ...1031-aab323465866_agent_sandbox_support.py | 125 ++++++++++++++++++ ...27822d22895_add_workflow_comments_table.py | 109 +++++++++++++++ 9 files changed, 234 insertions(+), 400 deletions(-) delete mode 100644 api/migrations/versions/2026_01_08_1031-aab323465866_sandbox_providers.py delete mode 100644 api/migrations/versions/2026_01_08_1617-85c8b4a64f53_add_llm_generation_detail_table.py delete mode 100644 api/migrations/versions/2026_01_14_1215-a1b2c3d4e5f6_add_app_asset_drafts_table.py delete mode 100644 api/migrations/versions/2026_01_15_1649-d88f3edbd99d_rename_app_assets.py delete mode 100644 api/migrations/versions/2026_01_16_1728-45471e916693_sandbox_provider_configure_type.py delete mode 100644 api/migrations/versions/2026_01_17_1726-227822d22895_add_workflow_comments_table.py delete mode 100644 api/migrations/versions/2026_01_21_0030-201d71cc4f34_add_default_sandbox_system_config.py create mode 100644 api/migrations/versions/2026_02_09_1031-aab323465866_agent_sandbox_support.py create mode 100644 api/migrations/versions/2026_02_09_1726-227822d22895_add_workflow_comments_table.py diff --git a/api/migrations/versions/2026_01_08_1031-aab323465866_sandbox_providers.py b/api/migrations/versions/2026_01_08_1031-aab323465866_sandbox_providers.py deleted file mode 100644 index f6146ead67..0000000000 --- a/api/migrations/versions/2026_01_08_1031-aab323465866_sandbox_providers.py +++ /dev/null @@ -1,56 +0,0 @@ -"""sandbox_providers - -Revision ID: aab323465866 -Revises: 788d3099ae3a -Create Date: 2026-01-08 10:31:05.062722 - -""" -from alembic import op -import models as models -import sqlalchemy as sa - -# revision identifiers, used by Alembic. -revision = 'aab323465866' -down_revision = '788d3099ae3a' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('sandbox_provider_system_config', - sa.Column('id', models.types.StringUUID(), nullable=False), - sa.Column('provider_type', sa.String(length=50), nullable=False, comment='e2b, docker, local'), - sa.Column('encrypted_config', models.types.LongText(), nullable=False, comment='Encrypted config JSON'), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.PrimaryKeyConstraint('id', name='sandbox_provider_system_config_pkey'), - sa.UniqueConstraint('provider_type', name='unique_sandbox_provider_system_config_type') - ) - op.create_table('sandbox_providers', - sa.Column('id', models.types.StringUUID(), nullable=False), - sa.Column('tenant_id', models.types.StringUUID(), nullable=False), - sa.Column('provider_type', sa.String(length=50), nullable=False, comment='e2b, docker, local'), - sa.Column('encrypted_config', models.types.LongText(), nullable=False, comment='Encrypted config JSON'), - sa.Column('is_active', sa.Boolean(), server_default=sa.text('false'), nullable=False), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.PrimaryKeyConstraint('id', name='sandbox_provider_pkey'), - sa.UniqueConstraint('tenant_id', 'provider_type', name='unique_sandbox_provider_tenant_type') - ) - with op.batch_alter_table('sandbox_providers', schema=None) as batch_op: - batch_op.create_index('idx_sandbox_providers_tenant_active', ['tenant_id', 'is_active'], unique=False) - batch_op.create_index('idx_sandbox_providers_tenant_id', ['tenant_id'], unique=False) - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('sandbox_providers', schema=None) as batch_op: - batch_op.drop_index('idx_sandbox_providers_tenant_id') - batch_op.drop_index('idx_sandbox_providers_tenant_active') - - op.drop_table('sandbox_providers') - op.drop_table('sandbox_provider_system_config') - # ### end Alembic commands ### diff --git a/api/migrations/versions/2026_01_08_1617-85c8b4a64f53_add_llm_generation_detail_table.py b/api/migrations/versions/2026_01_08_1617-85c8b4a64f53_add_llm_generation_detail_table.py deleted file mode 100644 index 0965e8ca0f..0000000000 --- a/api/migrations/versions/2026_01_08_1617-85c8b4a64f53_add_llm_generation_detail_table.py +++ /dev/null @@ -1,45 +0,0 @@ -"""add llm generation detail table. - -Revision ID: 85c8b4a64f53 -Revises: 7bb281b7a422 -Create Date: 2025-12-10 16:17:46.597669 - -""" -from alembic import op -import models as models -import sqlalchemy as sa - -# revision identifiers, used by Alembic. -revision = '85c8b4a64f53' -down_revision = 'aab323465866' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('llm_generation_details', - sa.Column('id', models.types.StringUUID(), nullable=False), - sa.Column('tenant_id', models.types.StringUUID(), nullable=False), - sa.Column('app_id', models.types.StringUUID(), nullable=False), - sa.Column('message_id', models.types.StringUUID(), nullable=True), - sa.Column('workflow_run_id', models.types.StringUUID(), nullable=True), - sa.Column('node_id', sa.String(length=255), nullable=True), - sa.Column('reasoning_content', models.types.LongText(), nullable=True), - sa.Column('tool_calls', models.types.LongText(), nullable=True), - sa.Column('sequence', models.types.LongText(), nullable=True), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.CheckConstraint('(message_id IS NOT NULL AND workflow_run_id IS NULL AND node_id IS NULL) OR (message_id IS NULL AND workflow_run_id IS NOT NULL AND node_id IS NOT NULL)', name=op.f('llm_generation_details_ck_llm_generation_detail_assoc_mode_check')), - sa.PrimaryKeyConstraint('id', name='llm_generation_detail_pkey'), - sa.UniqueConstraint('message_id', name=op.f('llm_generation_details_message_id_key')) - ) - with op.batch_alter_table('llm_generation_details', schema=None) as batch_op: - batch_op.create_index('idx_llm_generation_detail_message', ['message_id'], unique=False) - batch_op.create_index('idx_llm_generation_detail_workflow', ['workflow_run_id', 'node_id'], unique=False) - - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('llm_generation_details') - # ### end Alembic commands ### diff --git a/api/migrations/versions/2026_01_14_1215-a1b2c3d4e5f6_add_app_asset_drafts_table.py b/api/migrations/versions/2026_01_14_1215-a1b2c3d4e5f6_add_app_asset_drafts_table.py deleted file mode 100644 index 6f847683fd..0000000000 --- a/api/migrations/versions/2026_01_14_1215-a1b2c3d4e5f6_add_app_asset_drafts_table.py +++ /dev/null @@ -1,39 +0,0 @@ -"""add app_asset_drafts table. - -Revision ID: a1b2c3d4e5f6 -Revises: 85c8b4a64f53 -Create Date: 2026-01-14 12:15:00.000000 - -""" - -import sqlalchemy as sa -from alembic import op - -import models - -revision = "a1b2c3d4e5f6" -down_revision = "85c8b4a64f53" -branch_labels = None -depends_on = None - - -def upgrade(): - op.create_table( - "app_asset_drafts", - sa.Column("id", models.types.StringUUID(), nullable=False), - sa.Column("tenant_id", models.types.StringUUID(), nullable=False), - sa.Column("app_id", models.types.StringUUID(), nullable=False), - sa.Column("version", sa.String(length=255), nullable=False), - sa.Column("asset_tree", models.types.LongText(), nullable=False), - sa.Column("created_by", models.types.StringUUID(), nullable=False), - sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), - sa.Column("updated_by", models.types.StringUUID(), nullable=True), - sa.Column("updated_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), - sa.PrimaryKeyConstraint("id", name="app_asset_draft_pkey"), - ) - with op.batch_alter_table("app_asset_drafts", schema=None) as batch_op: - batch_op.create_index("app_asset_draft_version_idx", ["tenant_id", "app_id", "version"], unique=False) - - -def downgrade(): - op.drop_table("app_asset_drafts") diff --git a/api/migrations/versions/2026_01_15_1649-d88f3edbd99d_rename_app_assets.py b/api/migrations/versions/2026_01_15_1649-d88f3edbd99d_rename_app_assets.py deleted file mode 100644 index 7acf4b17da..0000000000 --- a/api/migrations/versions/2026_01_15_1649-d88f3edbd99d_rename_app_assets.py +++ /dev/null @@ -1,68 +0,0 @@ -"""rename_app_assets - -Revision ID: d88f3edbd99d -Revises: a1b2c3d4e5f6 -Create Date: 2026-01-15 16:49:11.833689 - -""" -from alembic import op -import models as models -import sqlalchemy as sa -from sqlalchemy.dialects import postgresql - -# revision identifiers, used by Alembic. -revision = 'd88f3edbd99d' -down_revision = 'a1b2c3d4e5f6' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('app_assets', - sa.Column('id', models.types.StringUUID(), nullable=False), - sa.Column('tenant_id', models.types.StringUUID(), nullable=False), - sa.Column('app_id', models.types.StringUUID(), nullable=False), - sa.Column('version', sa.String(length=255), nullable=False), - sa.Column('asset_tree', models.types.LongText(), nullable=False), - sa.Column('created_by', models.types.StringUUID(), nullable=False), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('updated_by', models.types.StringUUID(), nullable=True), - sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.PrimaryKeyConstraint('id', name='app_assets_pkey') - ) - with op.batch_alter_table('app_assets', schema=None) as batch_op: - batch_op.create_index('app_assets_version_idx', ['tenant_id', 'app_id', 'version'], unique=False) - - with op.batch_alter_table('app_asset_drafts', schema=None) as batch_op: - batch_op.drop_index(batch_op.f('app_asset_draft_version_idx')) - - op.drop_table('app_asset_drafts') - with op.batch_alter_table('trigger_oauth_tenant_clients', schema=None) as batch_op: - batch_op.alter_column('plugin_id', - existing_type=sa.VARCHAR(length=512), - type_=sa.String(length=255), - existing_nullable=False) - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('app_asset_drafts', - sa.Column('id', sa.UUID(), autoincrement=False, nullable=False), - sa.Column('tenant_id', sa.UUID(), autoincrement=False, nullable=False), - sa.Column('app_id', sa.UUID(), autoincrement=False, nullable=False), - sa.Column('version', sa.VARCHAR(length=255), autoincrement=False, nullable=False), - sa.Column('asset_tree', sa.TEXT(), autoincrement=False, nullable=False), - sa.Column('created_by', sa.UUID(), autoincrement=False, nullable=False), - sa.Column('created_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=False), - sa.Column('updated_by', sa.UUID(), autoincrement=False, nullable=True), - sa.Column('updated_at', postgresql.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), autoincrement=False, nullable=False), - sa.PrimaryKeyConstraint('id', name=op.f('app_asset_draft_pkey')) - ) - with op.batch_alter_table('app_asset_drafts', schema=None) as batch_op: - batch_op.create_index(batch_op.f('app_asset_draft_version_idx'), ['tenant_id', 'app_id', 'version'], unique=False) - - op.drop_table('app_assets') - # ### end Alembic commands ### diff --git a/api/migrations/versions/2026_01_16_1728-45471e916693_sandbox_provider_configure_type.py b/api/migrations/versions/2026_01_16_1728-45471e916693_sandbox_provider_configure_type.py deleted file mode 100644 index 13ef816e4c..0000000000 --- a/api/migrations/versions/2026_01_16_1728-45471e916693_sandbox_provider_configure_type.py +++ /dev/null @@ -1,35 +0,0 @@ -"""sandbox_provider_configure_type - -Revision ID: 45471e916693 -Revises: d88f3edbd99d -Create Date: 2026-01-16 17:28:46.691473 - -""" -from alembic import op -import models as models -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '45471e916693' -down_revision = 'd88f3edbd99d' -branch_labels = None -depends_on = None - - -def upgrade(): - - with op.batch_alter_table('sandbox_providers', schema=None) as batch_op: - batch_op.add_column(sa.Column('configure_type', sa.String(length=20), server_default='user', nullable=False)) - batch_op.drop_constraint(batch_op.f('unique_sandbox_provider_tenant_type'), type_='unique') - batch_op.create_unique_constraint('unique_sandbox_provider_tenant_type', ['tenant_id', 'provider_type', 'configure_type']) - - # ### end Alembic commands ### - - -def downgrade(): - with op.batch_alter_table('sandbox_providers', schema=None) as batch_op: - batch_op.drop_constraint('unique_sandbox_provider_tenant_type', type_='unique') - batch_op.create_unique_constraint(batch_op.f('unique_sandbox_provider_tenant_type'), ['tenant_id', 'provider_type'], postgresql_nulls_not_distinct=False) - batch_op.drop_column('configure_type') - diff --git a/api/migrations/versions/2026_01_17_1726-227822d22895_add_workflow_comments_table.py b/api/migrations/versions/2026_01_17_1726-227822d22895_add_workflow_comments_table.py deleted file mode 100644 index e69195de8d..0000000000 --- a/api/migrations/versions/2026_01_17_1726-227822d22895_add_workflow_comments_table.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Add workflow comments table - -Revision ID: 227822d22895 -Revises: 201d71cc4f34 -Create Date: 2025-08-22 17:26:15.255980 - -""" -from alembic import op -import models as models -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '227822d22895' -down_revision = '201d71cc4f34' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('workflow_comments', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuidv7()'), nullable=False), - sa.Column('tenant_id', models.types.StringUUID(), nullable=False), - sa.Column('app_id', models.types.StringUUID(), nullable=False), - sa.Column('position_x', sa.Float(), nullable=False), - sa.Column('position_y', sa.Float(), nullable=False), - sa.Column('content', sa.Text(), nullable=False), - sa.Column('created_by', models.types.StringUUID(), nullable=False), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('resolved', sa.Boolean(), server_default=sa.text('false'), nullable=False), - sa.Column('resolved_at', sa.DateTime(), nullable=True), - sa.Column('resolved_by', models.types.StringUUID(), nullable=True), - sa.PrimaryKeyConstraint('id', name='workflow_comments_pkey') - ) - with op.batch_alter_table('workflow_comments', schema=None) as batch_op: - batch_op.create_index('workflow_comments_app_idx', ['tenant_id', 'app_id'], unique=False) - batch_op.create_index('workflow_comments_created_at_idx', ['created_at'], unique=False) - - op.create_table('workflow_comment_replies', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuidv7()'), nullable=False), - sa.Column('comment_id', models.types.StringUUID(), nullable=False), - sa.Column('content', sa.Text(), nullable=False), - sa.Column('created_by', models.types.StringUUID(), nullable=False), - sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), - sa.ForeignKeyConstraint(['comment_id'], ['workflow_comments.id'], name=op.f('workflow_comment_replies_comment_id_fkey'), ondelete='CASCADE'), - sa.PrimaryKeyConstraint('id', name='workflow_comment_replies_pkey') - ) - with op.batch_alter_table('workflow_comment_replies', schema=None) as batch_op: - batch_op.create_index('comment_replies_comment_idx', ['comment_id'], unique=False) - batch_op.create_index('comment_replies_created_at_idx', ['created_at'], unique=False) - - op.create_table('workflow_comment_mentions', - sa.Column('id', models.types.StringUUID(), server_default=sa.text('uuidv7()'), nullable=False), - sa.Column('comment_id', models.types.StringUUID(), nullable=False), - sa.Column('reply_id', models.types.StringUUID(), nullable=True), - sa.Column('mentioned_user_id', models.types.StringUUID(), nullable=False), - sa.ForeignKeyConstraint(['comment_id'], ['workflow_comments.id'], name=op.f('workflow_comment_mentions_comment_id_fkey'), ondelete='CASCADE'), - sa.ForeignKeyConstraint(['reply_id'], ['workflow_comment_replies.id'], name=op.f('workflow_comment_mentions_reply_id_fkey'), ondelete='CASCADE'), - sa.PrimaryKeyConstraint('id', name='workflow_comment_mentions_pkey') - ) - with op.batch_alter_table('workflow_comment_mentions', schema=None) as batch_op: - batch_op.create_index('comment_mentions_comment_idx', ['comment_id'], unique=False) - batch_op.create_index('comment_mentions_reply_idx', ['reply_id'], unique=False) - batch_op.create_index('comment_mentions_user_idx', ['mentioned_user_id'], unique=False) - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('workflow_comment_mentions', schema=None) as batch_op: - batch_op.drop_index('comment_mentions_user_idx') - batch_op.drop_index('comment_mentions_reply_idx') - batch_op.drop_index('comment_mentions_comment_idx') - - op.drop_table('workflow_comment_mentions') - with op.batch_alter_table('workflow_comment_replies', schema=None) as batch_op: - batch_op.drop_index('comment_replies_created_at_idx') - batch_op.drop_index('comment_replies_comment_idx') - - op.drop_table('workflow_comment_replies') - with op.batch_alter_table('workflow_comments', schema=None) as batch_op: - batch_op.drop_index('workflow_comments_created_at_idx') - batch_op.drop_index('workflow_comments_app_idx') - - op.drop_table('workflow_comments') - # ### end Alembic commands ### diff --git a/api/migrations/versions/2026_01_21_0030-201d71cc4f34_add_default_sandbox_system_config.py b/api/migrations/versions/2026_01_21_0030-201d71cc4f34_add_default_sandbox_system_config.py deleted file mode 100644 index f6a6eb5da8..0000000000 --- a/api/migrations/versions/2026_01_21_0030-201d71cc4f34_add_default_sandbox_system_config.py +++ /dev/null @@ -1,67 +0,0 @@ -"""add_default_sandbox_system_config - -Revision ID: 201d71cc4f34 -Revises: 45471e916693 -Create Date: 2026-01-21 00:30:01.908057 - -""" -from uuid import uuid4 - -from alembic import op -import models as models -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '201d71cc4f34' -down_revision = '45471e916693' -branch_labels = None -depends_on = None - - -def upgrade(): - # Import encryption utility - from core.tools.utils.system_encryption import encrypt_system_params - - # Define the default SSH configuration for agentbox - ssh_config = { - "ssh_host": "agentbox", - "ssh_port": "22", - "ssh_username": "agentbox", - "ssh_password": "agentbox", - "base_working_path": "/workspace/sandboxes", - } - - # Encrypt the configuration - encrypted_config = encrypt_system_params(ssh_config) - - # Generate UUID for the record - record_id = str(uuid4()) - - # Insert the default SSH sandbox system config if it doesn't exist - op.execute( - sa.text( - """ - INSERT INTO sandbox_provider_system_config - (id, provider_type, encrypted_config, created_at, updated_at) - VALUES (:id, :provider_type, :encrypted_config, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) - ON CONFLICT (provider_type) DO NOTHING - """ - ).bindparams( - id=record_id, - provider_type='ssh', - encrypted_config=encrypted_config - ) - ) - - -def downgrade(): - # Delete the default SSH sandbox system config - op.execute( - sa.text( - """ - DELETE FROM sandbox_provider_system_config - WHERE provider_type = :provider_type - """ - ).bindparams(provider_type='ssh') - ) diff --git a/api/migrations/versions/2026_02_09_1031-aab323465866_agent_sandbox_support.py b/api/migrations/versions/2026_02_09_1031-aab323465866_agent_sandbox_support.py new file mode 100644 index 0000000000..77a8e11cb1 --- /dev/null +++ b/api/migrations/versions/2026_02_09_1031-aab323465866_agent_sandbox_support.py @@ -0,0 +1,125 @@ +"""Add sandbox providers, app assets, and LLM detail tables. + +Revision ID: aab323465866 +Revises: c3df22613c99 +Create Date: 2026-02-09 10:31:05.062722 + +""" + +from uuid import uuid4 + +from alembic import op +import models as models +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision = "aab323465866" +down_revision = "c3df22613c99" +branch_labels = None +depends_on = None + + +def upgrade(): + from core.tools.utils.system_encryption import encrypt_system_params + + op.create_table( + "sandbox_provider_system_config", + sa.Column("id", models.types.StringUUID(), nullable=False), + sa.Column("provider_type", sa.String(length=50), nullable=False, comment="e2b, docker, local, ssh"), + sa.Column("encrypted_config", models.types.LongText(), nullable=False, comment="Encrypted config JSON"), + sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.Column("updated_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.PrimaryKeyConstraint("id", name="sandbox_provider_system_config_pkey"), + sa.UniqueConstraint("provider_type", name="unique_sandbox_provider_system_config_type"), + ) + op.create_table( + "sandbox_providers", + sa.Column("id", models.types.StringUUID(), nullable=False), + sa.Column("tenant_id", models.types.StringUUID(), nullable=False), + sa.Column("provider_type", sa.String(length=50), nullable=False, comment="e2b, docker, local, ssh"), + sa.Column("configure_type", sa.String(length=20), server_default="user", nullable=False), + sa.Column("encrypted_config", models.types.LongText(), nullable=False, comment="Encrypted config JSON"), + sa.Column("is_active", sa.Boolean(), server_default=sa.text("false"), nullable=False), + sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.Column("updated_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.PrimaryKeyConstraint("id", name="sandbox_provider_pkey"), + sa.UniqueConstraint("tenant_id", "provider_type", "configure_type", name="unique_sandbox_provider_tenant_type"), + ) + with op.batch_alter_table("sandbox_providers", schema=None) as batch_op: + batch_op.create_index("idx_sandbox_providers_tenant_active", ["tenant_id", "is_active"], unique=False) + batch_op.create_index("idx_sandbox_providers_tenant_id", ["tenant_id"], unique=False) + + op.create_table( + "llm_generation_details", + sa.Column("id", models.types.StringUUID(), nullable=False), + sa.Column("tenant_id", models.types.StringUUID(), nullable=False), + sa.Column("app_id", models.types.StringUUID(), nullable=False), + sa.Column("message_id", models.types.StringUUID(), nullable=True), + sa.Column("workflow_run_id", models.types.StringUUID(), nullable=True), + sa.Column("node_id", sa.String(length=255), nullable=True), + sa.Column("reasoning_content", models.types.LongText(), nullable=True), + sa.Column("tool_calls", models.types.LongText(), nullable=True), + sa.Column("sequence", models.types.LongText(), nullable=True), + sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.CheckConstraint( + "(message_id IS NOT NULL AND workflow_run_id IS NULL AND node_id IS NULL) OR (message_id IS NULL AND workflow_run_id IS NOT NULL AND node_id IS NOT NULL)", + name=op.f("llm_generation_details_ck_llm_generation_detail_assoc_mode_check"), + ), + sa.PrimaryKeyConstraint("id", name="llm_generation_detail_pkey"), + sa.UniqueConstraint("message_id", name=op.f("llm_generation_details_message_id_key")), + ) + with op.batch_alter_table("llm_generation_details", schema=None) as batch_op: + batch_op.create_index("idx_llm_generation_detail_message", ["message_id"], unique=False) + batch_op.create_index("idx_llm_generation_detail_workflow", ["workflow_run_id", "node_id"], unique=False) + + op.create_table( + "app_assets", + sa.Column("id", models.types.StringUUID(), nullable=False), + sa.Column("tenant_id", models.types.StringUUID(), nullable=False), + sa.Column("app_id", models.types.StringUUID(), nullable=False), + sa.Column("version", sa.String(length=255), nullable=False), + sa.Column("asset_tree", models.types.LongText(), nullable=False), + sa.Column("created_by", models.types.StringUUID(), nullable=False), + sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.Column("updated_by", models.types.StringUUID(), nullable=True), + sa.Column("updated_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.PrimaryKeyConstraint("id", name="app_assets_pkey"), + ) + with op.batch_alter_table("app_assets", schema=None) as batch_op: + batch_op.create_index("app_assets_version_idx", ["tenant_id", "app_id", "version"], unique=False) + + ssh_config = { + "ssh_host": "agentbox", + "ssh_port": "22", + "ssh_username": "agentbox", + "ssh_password": "agentbox", + "base_working_path": "/workspace/sandboxes", + } + encrypted_config = encrypt_system_params(ssh_config) + + op.execute( + sa.text( + """ + INSERT INTO sandbox_provider_system_config + (id, provider_type, encrypted_config, created_at, updated_at) + VALUES (:id, :provider_type, :encrypted_config, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) + ON CONFLICT (provider_type) DO NOTHING + """ + ).bindparams( + id=str(uuid4()), + provider_type="ssh", + encrypted_config=encrypted_config, + ) + ) + + +def downgrade(): + op.drop_table("app_assets") + op.drop_table("llm_generation_details") + + with op.batch_alter_table("sandbox_providers", schema=None) as batch_op: + batch_op.drop_index("idx_sandbox_providers_tenant_id") + batch_op.drop_index("idx_sandbox_providers_tenant_active") + + op.drop_table("sandbox_providers") + op.drop_table("sandbox_provider_system_config") diff --git a/api/migrations/versions/2026_02_09_1726-227822d22895_add_workflow_comments_table.py b/api/migrations/versions/2026_02_09_1726-227822d22895_add_workflow_comments_table.py new file mode 100644 index 0000000000..af5e04a0e8 --- /dev/null +++ b/api/migrations/versions/2026_02_09_1726-227822d22895_add_workflow_comments_table.py @@ -0,0 +1,109 @@ +"""Add workflow comments table + +Revision ID: 227822d22895 +Revises: aab323465866 +Create Date: 2026-02-09 17:26:15.255980 + +""" + +from alembic import op +import models as models +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "227822d22895" +down_revision = "aab323465866" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "workflow_comments", + sa.Column("id", models.types.StringUUID(), server_default=sa.text("uuidv7()"), nullable=False), + sa.Column("tenant_id", models.types.StringUUID(), nullable=False), + sa.Column("app_id", models.types.StringUUID(), nullable=False), + sa.Column("position_x", sa.Float(), nullable=False), + sa.Column("position_y", sa.Float(), nullable=False), + sa.Column("content", sa.Text(), nullable=False), + sa.Column("created_by", models.types.StringUUID(), nullable=False), + sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.Column("updated_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.Column("resolved", sa.Boolean(), server_default=sa.text("false"), nullable=False), + sa.Column("resolved_at", sa.DateTime(), nullable=True), + sa.Column("resolved_by", models.types.StringUUID(), nullable=True), + sa.PrimaryKeyConstraint("id", name="workflow_comments_pkey"), + ) + with op.batch_alter_table("workflow_comments", schema=None) as batch_op: + batch_op.create_index("workflow_comments_app_idx", ["tenant_id", "app_id"], unique=False) + batch_op.create_index("workflow_comments_created_at_idx", ["created_at"], unique=False) + + op.create_table( + "workflow_comment_replies", + sa.Column("id", models.types.StringUUID(), server_default=sa.text("uuidv7()"), nullable=False), + sa.Column("comment_id", models.types.StringUUID(), nullable=False), + sa.Column("content", sa.Text(), nullable=False), + sa.Column("created_by", models.types.StringUUID(), nullable=False), + sa.Column("created_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.Column("updated_at", sa.DateTime(), server_default=sa.text("CURRENT_TIMESTAMP"), nullable=False), + sa.ForeignKeyConstraint( + ["comment_id"], + ["workflow_comments.id"], + name=op.f("workflow_comment_replies_comment_id_fkey"), + ondelete="CASCADE", + ), + sa.PrimaryKeyConstraint("id", name="workflow_comment_replies_pkey"), + ) + with op.batch_alter_table("workflow_comment_replies", schema=None) as batch_op: + batch_op.create_index("comment_replies_comment_idx", ["comment_id"], unique=False) + batch_op.create_index("comment_replies_created_at_idx", ["created_at"], unique=False) + + op.create_table( + "workflow_comment_mentions", + sa.Column("id", models.types.StringUUID(), server_default=sa.text("uuidv7()"), nullable=False), + sa.Column("comment_id", models.types.StringUUID(), nullable=False), + sa.Column("reply_id", models.types.StringUUID(), nullable=True), + sa.Column("mentioned_user_id", models.types.StringUUID(), nullable=False), + sa.ForeignKeyConstraint( + ["comment_id"], + ["workflow_comments.id"], + name=op.f("workflow_comment_mentions_comment_id_fkey"), + ondelete="CASCADE", + ), + sa.ForeignKeyConstraint( + ["reply_id"], + ["workflow_comment_replies.id"], + name=op.f("workflow_comment_mentions_reply_id_fkey"), + ondelete="CASCADE", + ), + sa.PrimaryKeyConstraint("id", name="workflow_comment_mentions_pkey"), + ) + with op.batch_alter_table("workflow_comment_mentions", schema=None) as batch_op: + batch_op.create_index("comment_mentions_comment_idx", ["comment_id"], unique=False) + batch_op.create_index("comment_mentions_reply_idx", ["reply_id"], unique=False) + batch_op.create_index("comment_mentions_user_idx", ["mentioned_user_id"], unique=False) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("workflow_comment_mentions", schema=None) as batch_op: + batch_op.drop_index("comment_mentions_user_idx") + batch_op.drop_index("comment_mentions_reply_idx") + batch_op.drop_index("comment_mentions_comment_idx") + + op.drop_table("workflow_comment_mentions") + with op.batch_alter_table("workflow_comment_replies", schema=None) as batch_op: + batch_op.drop_index("comment_replies_created_at_idx") + batch_op.drop_index("comment_replies_comment_idx") + + op.drop_table("workflow_comment_replies") + with op.batch_alter_table("workflow_comments", schema=None) as batch_op: + batch_op.drop_index("workflow_comments_created_at_idx") + batch_op.drop_index("workflow_comments_app_idx") + + op.drop_table("workflow_comments") + # ### end Alembic commands ###