"""add automation tables (阶段5 自动化闭环): auto_sessions / auto_actions / auto_approval_tickets / auto_scenario_configs / auto_rule_versions / auto_action_logs / auto_mapping_cache Revision ID: 044_automation Revises: 043_knowledge_iteration Create Date: 2026-07-10 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision: str = '044_automation' down_revision: Union[str, None] = '043_knowledge_iteration' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # -------------------------------------------------------------------------- # 1. 自动化处置会话 auto_sessions # -------------------------------------------------------------------------- op.create_table( 'auto_sessions', sa.Column('id', sa.String(36), primary_key=True), sa.Column('conversation_id', sa.String(36), nullable=True, index=True), sa.Column('employee_id', sa.String(64), nullable=False, index=True), sa.Column('agent_id', sa.String(64), nullable=True, index=True), sa.Column('scenario_key', sa.String(64), nullable=True, index=True), sa.Column('status', sa.String(20), nullable=False, server_default='created', index=True), sa.Column('mode', sa.String(20), nullable=False, server_default='real_exec'), sa.Column('confidence', sa.Float(), nullable=False, server_default='0.0'), sa.Column('intent', sa.JSON(), nullable=True), sa.Column('current_action_id', sa.String(36), nullable=True), sa.Column('title', sa.String(256), nullable=False, server_default=''), sa.Column('auto_close_at', sa.DateTime(timezone=True), nullable=True), sa.Column('resolved_at', sa.DateTime(timezone=True), nullable=True), sa.Column('closed_by', sa.String(64), nullable=True), sa.Column('meta', sa.JSON(), nullable=True), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_session_employee', 'auto_sessions', ['employee_id']) op.create_index('idx_auto_session_status', 'auto_sessions', ['status']) # -------------------------------------------------------------------------- # 2. 处置动作 auto_actions # -------------------------------------------------------------------------- op.create_table( 'auto_actions', sa.Column('id', sa.String(36), primary_key=True), sa.Column('session_id', sa.String(36), nullable=False, index=True), sa.Column('action_index', sa.Integer(), nullable=False, server_default='0'), sa.Column('action_type', sa.String(64), nullable=False, server_default=''), sa.Column('adapter', sa.String(32), nullable=False, server_default=''), sa.Column('risk_level', sa.String(16), nullable=False, server_default='read'), sa.Column('title', sa.String(256), nullable=False, server_default=''), sa.Column('description', sa.Text(), nullable=False, server_default=''), sa.Column('status', sa.String(20), nullable=False, server_default='pending', index=True), sa.Column('payload', sa.JSON(), nullable=True), sa.Column('result', sa.JSON(), nullable=True), sa.Column('error', sa.Text(), nullable=True), sa.Column('approved_by', sa.String(64), nullable=True), sa.Column('approved_at', sa.DateTime(timezone=True), nullable=True), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_action_session', 'auto_actions', ['session_id']) op.create_index('idx_auto_action_status', 'auto_actions', ['status']) # -------------------------------------------------------------------------- # 3. 审批单 auto_approval_tickets # -------------------------------------------------------------------------- op.create_table( 'auto_approval_tickets', sa.Column('id', sa.String(36), primary_key=True), sa.Column('action_id', sa.String(36), nullable=False, index=True), sa.Column('session_id', sa.String(36), nullable=False, index=True), sa.Column('approver_id', sa.String(64), nullable=True), sa.Column('channel', sa.String(16), nullable=False, server_default='agent'), sa.Column('status', sa.String(20), nullable=False, server_default='pending', index=True), sa.Column('reason', sa.Text(), nullable=True), sa.Column('decision_note', sa.Text(), nullable=True), sa.Column('decided_at', sa.DateTime(timezone=True), nullable=True), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_approval_action', 'auto_approval_tickets', ['action_id']) op.create_index('idx_auto_approval_session', 'auto_approval_tickets', ['session_id']) # -------------------------------------------------------------------------- # 4. 场景配置 auto_scenario_configs # -------------------------------------------------------------------------- op.create_table( 'auto_scenario_configs', sa.Column('id', sa.String(36), primary_key=True), sa.Column('scenario_key', sa.String(64), nullable=False, unique=True, index=True), sa.Column('name', sa.String(128), nullable=False, server_default=''), sa.Column('description', sa.Text(), nullable=False, server_default=''), sa.Column('enabled', sa.Boolean(), nullable=False, server_default=sa.true()), sa.Column('trigger_conditions', sa.JSON(), nullable=True), sa.Column('actions', sa.JSON(), nullable=True), sa.Column('approval_strategy', sa.JSON(), nullable=True), sa.Column('current_version_id', sa.String(36), nullable=True), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_scenario_key', 'auto_scenario_configs', ['scenario_key']) # -------------------------------------------------------------------------- # 5. 规则版本 auto_rule_versions # -------------------------------------------------------------------------- op.create_table( 'auto_rule_versions', sa.Column('id', sa.String(36), primary_key=True), sa.Column('scenario_key', sa.String(64), nullable=False, index=True), sa.Column('version', sa.Integer(), nullable=False, server_default='1'), sa.Column('content', sa.JSON(), nullable=True), sa.Column('status', sa.String(20), nullable=False, server_default='draft', index=True), sa.Column('canary_percent', sa.Integer(), nullable=False, server_default='100'), sa.Column('created_by', sa.String(64), nullable=True), sa.Column('remark', sa.Text(), nullable=False, server_default=''), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_rule_version_scenario', 'auto_rule_versions', ['scenario_key']) # -------------------------------------------------------------------------- # 6. 外部调用审计日志 auto_action_logs # -------------------------------------------------------------------------- op.create_table( 'auto_action_logs', sa.Column('id', sa.String(36), primary_key=True), sa.Column('session_id', sa.String(36), nullable=True, index=True), sa.Column('action_id', sa.String(36), nullable=True, index=True), sa.Column('employee_id', sa.String(64), nullable=True), sa.Column('event', sa.String(128), nullable=False, server_default=''), sa.Column('direction', sa.String(8), nullable=False, server_default='out'), sa.Column('system', sa.String(32), nullable=False, server_default='internal'), sa.Column('request', sa.JSON(), nullable=True), sa.Column('response', sa.JSON(), nullable=True), sa.Column('status', sa.String(32), nullable=False, server_default=''), sa.Column('latency_ms', sa.Integer(), nullable=True), sa.Column('error', sa.Text(), nullable=True), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_action_log_session', 'auto_action_logs', ['session_id']) op.create_index('idx_auto_action_log_action', 'auto_action_logs', ['action_id']) # -------------------------------------------------------------------------- # 7. 映射缓存 auto_mapping_cache # -------------------------------------------------------------------------- op.create_table( 'auto_mapping_cache', sa.Column('id', sa.String(36), primary_key=True), sa.Column('employee_id', sa.String(64), nullable=False, index=True), sa.Column('source', sa.String(32), nullable=False, server_default='lianruan'), sa.Column('mapped_data', sa.JSON(), nullable=True), sa.Column('expires_at', sa.DateTime(timezone=True), nullable=True), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), ) op.create_index('idx_auto_mapping_employee', 'auto_mapping_cache', ['employee_id']) def downgrade() -> None: op.drop_table('auto_mapping_cache') op.drop_table('auto_action_logs') op.drop_table('auto_rule_versions') op.drop_table('auto_scenario_configs') op.drop_table('auto_approval_tickets') op.drop_table('auto_actions') op.drop_table('auto_sessions')