Files
aiagent/backend/alembic/versions/001_initial_migration.py
2026-01-19 00:09:36 +08:00

218 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""initial migration
Revision ID: 001
Revises:
Create Date: 2024-01-01 00:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
# revision identifiers, used by Alembic.
revision = '001'
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
# 创建用户表
op.create_table(
'users',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='用户ID'),
sa.Column('username', sa.String(length=50), nullable=False, comment='用户名'),
sa.Column('email', sa.String(length=100), nullable=False, comment='邮箱'),
sa.Column('password_hash', sa.String(length=255), nullable=False, comment='密码哈希'),
sa.Column('role', sa.String(length=20), server_default='user', nullable=True, comment='角色: admin/user'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=True, comment='更新时间'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('username'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
# 创建工作流表
op.create_table(
'workflows',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='工作流ID'),
sa.Column('name', sa.String(length=100), nullable=False, comment='工作流名称'),
sa.Column('description', sa.Text(), nullable=True, comment='描述'),
sa.Column('nodes', sa.JSON(), nullable=False, comment='节点配置'),
sa.Column('edges', sa.JSON(), nullable=False, comment='边配置'),
sa.Column('version', sa.Integer(), server_default='1', nullable=True, comment='版本号'),
sa.Column('status', sa.String(length=20), server_default='draft', nullable=True, comment='状态: draft/published/running/stopped'),
sa.Column('user_id', mysql.CHAR(length=36), nullable=True, comment='创建者ID'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=True, comment='更新时间'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_workflows_user_id', 'workflows', ['user_id'], unique=False)
# 创建工作流版本表
op.create_table(
'workflow_versions',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='版本ID'),
sa.Column('workflow_id', mysql.CHAR(length=36), nullable=False, comment='工作流ID'),
sa.Column('version', sa.Integer(), nullable=False, comment='版本号'),
sa.Column('name', sa.String(length=100), nullable=False, comment='工作流名称'),
sa.Column('description', sa.Text(), nullable=True, comment='描述'),
sa.Column('nodes', sa.JSON(), nullable=False, comment='节点配置'),
sa.Column('edges', sa.JSON(), nullable=False, comment='边配置'),
sa.Column('status', sa.String(length=20), server_default='draft', nullable=True, comment='状态: draft/published/running/stopped'),
sa.Column('created_by', mysql.CHAR(length=36), nullable=True, comment='创建者ID'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('comment', sa.Text(), nullable=True, comment='版本备注'),
sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
sa.ForeignKeyConstraint(['workflow_id'], ['workflows.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_workflow_versions_workflow_id', 'workflow_versions', ['workflow_id'], unique=False)
# 创建智能体表
op.create_table(
'agents',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='智能体ID'),
sa.Column('name', sa.String(length=100), nullable=False, comment='智能体名称'),
sa.Column('description', sa.Text(), nullable=True, comment='描述'),
sa.Column('workflow_config', sa.JSON(), nullable=False, comment='工作流配置'),
sa.Column('version', sa.Integer(), server_default='1', nullable=True, comment='版本号'),
sa.Column('status', sa.String(length=20), server_default='draft', nullable=True, comment='状态: draft/published/running/stopped'),
sa.Column('user_id', mysql.CHAR(length=36), nullable=True, comment='创建者ID'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=True, comment='更新时间'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_agents_user_id', 'agents', ['user_id'], unique=False)
# 创建执行记录表
op.create_table(
'executions',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='执行ID'),
sa.Column('workflow_id', mysql.CHAR(length=36), nullable=True, comment='工作流ID'),
sa.Column('agent_id', mysql.CHAR(length=36), nullable=True, comment='智能体ID'),
sa.Column('input_data', sa.JSON(), nullable=True, comment='输入数据'),
sa.Column('output_data', sa.JSON(), nullable=True, comment='输出数据'),
sa.Column('status', sa.String(length=20), server_default='pending', nullable=True, comment='状态: pending/running/completed/failed'),
sa.Column('task_id', sa.String(length=255), nullable=True, comment='Celery任务ID'),
sa.Column('error_message', sa.Text(), nullable=True, comment='错误信息'),
sa.Column('execution_time', sa.Integer(), nullable=True, comment='执行时间(毫秒)'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=True, comment='更新时间'),
sa.ForeignKeyConstraint(['agent_id'], ['agents.id'], ),
sa.ForeignKeyConstraint(['workflow_id'], ['workflows.id'], ),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_executions_workflow_id', 'executions', ['workflow_id'], unique=False)
op.create_index('ix_executions_agent_id', 'executions', ['agent_id'], unique=False)
op.create_index('ix_executions_status', 'executions', ['status'], unique=False)
# 创建执行日志表
op.create_table(
'execution_logs',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='日志ID'),
sa.Column('execution_id', mysql.CHAR(length=36), nullable=False, comment='执行ID'),
sa.Column('node_id', sa.String(length=100), nullable=True, comment='节点ID'),
sa.Column('node_type', sa.String(length=50), nullable=True, comment='节点类型'),
sa.Column('level', sa.String(length=20), nullable=False, comment='日志级别: info/warn/error/debug'),
sa.Column('message', sa.Text(), nullable=False, comment='日志消息'),
sa.Column('timestamp', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='时间戳'),
sa.Column('duration_ms', sa.Integer(), nullable=True, comment='执行时长(毫秒)'),
sa.Column('input_data', sa.JSON(), nullable=True, comment='输入数据'),
sa.Column('output_data', sa.JSON(), nullable=True, comment='输出数据'),
sa.Column('error_message', sa.Text(), nullable=True, comment='错误信息'),
sa.Column('additional_data', sa.JSON(), nullable=True, comment='附加数据'),
sa.ForeignKeyConstraint(['execution_id'], ['executions.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_execution_logs_execution_id', 'execution_logs', ['execution_id'], unique=False)
op.create_index('ix_execution_logs_node_id', 'execution_logs', ['node_id'], unique=False)
op.create_index('ix_execution_logs_level', 'execution_logs', ['level'], unique=False)
# 创建模型配置表
op.create_table(
'model_configs',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='配置ID'),
sa.Column('name', sa.String(length=100), nullable=False, comment='配置名称'),
sa.Column('provider', sa.String(length=50), nullable=False, comment='提供商: openai/claude/local'),
sa.Column('model_name', sa.String(length=100), nullable=False, comment='模型名称'),
sa.Column('api_key', sa.String(length=500), nullable=False, comment='API密钥加密存储'),
sa.Column('base_url', sa.String(length=255), nullable=True, comment='API地址'),
sa.Column('user_id', mysql.CHAR(length=36), nullable=True, comment='所属用户ID'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=True, comment='更新时间'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_model_configs_user_id', 'model_configs', ['user_id'], unique=False)
# 创建数据源表
op.create_table(
'data_sources',
sa.Column('id', mysql.CHAR(length=36), nullable=False, comment='数据源ID'),
sa.Column('name', sa.String(length=100), nullable=False, comment='数据源名称'),
sa.Column('type', sa.String(length=50), nullable=False, comment='数据源类型: mysql/postgresql/mongodb/redis/csv/json/api/s3'),
sa.Column('description', sa.Text(), nullable=True, comment='描述'),
sa.Column('config', sa.JSON(), nullable=False, comment='连接配置(加密存储敏感信息)'),
sa.Column('status', sa.String(length=20), server_default='active', nullable=True, comment='状态: active/inactive/error'),
sa.Column('user_id', mysql.CHAR(length=36), nullable=False, comment='创建者ID'),
sa.Column('last_connected_at', sa.DateTime(), nullable=True, comment='最后连接时间'),
sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=True, comment='创建时间'),
sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=True, comment='更新时间'),
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
mysql_charset='utf8mb4',
mysql_collate='utf8mb4_unicode_ci'
)
op.create_index('ix_data_sources_user_id', 'data_sources', ['user_id'], unique=False)
op.create_index('ix_data_sources_type', 'data_sources', ['type'], unique=False)
op.create_index('ix_data_sources_status', 'data_sources', ['status'], unique=False)
def downgrade() -> None:
# 删除所有表(按依赖关系逆序)
op.drop_index('ix_data_sources_status', table_name='data_sources')
op.drop_index('ix_data_sources_type', table_name='data_sources')
op.drop_index('ix_data_sources_user_id', table_name='data_sources')
op.drop_table('data_sources')
op.drop_index('ix_model_configs_user_id', table_name='model_configs')
op.drop_table('model_configs')
op.drop_index('ix_execution_logs_level', table_name='execution_logs')
op.drop_index('ix_execution_logs_node_id', table_name='execution_logs')
op.drop_index('ix_execution_logs_execution_id', table_name='execution_logs')
op.drop_table('execution_logs')
op.drop_index('ix_executions_status', table_name='executions')
op.drop_index('ix_executions_agent_id', table_name='executions')
op.drop_index('ix_executions_workflow_id', table_name='executions')
op.drop_table('executions')
op.drop_index('ix_agents_user_id', table_name='agents')
op.drop_table('agents')
op.drop_index('ix_workflow_versions_workflow_id', table_name='workflow_versions')
op.drop_table('workflow_versions')
op.drop_index('ix_workflows_user_id', table_name='workflows')
op.drop_table('workflows')
op.drop_table('users')