feat: Add base project structure with API and web components

This commit is contained in:
Ke Sun
2025-12-02 20:28:01 +08:00
parent f3de6d6cc9
commit c1adc62ec6
817 changed files with 111226 additions and 106 deletions

View File

@@ -0,0 +1,96 @@
"""20251124172719
Revision ID: a09d0e19cde6
Revises: 74bed22061db
Create Date: 2025-11-24 17:27:19.696895
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = 'a09d0e19cde6'
down_revision: Union[str, None] = '74bed22061db'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('agent_invocations',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('caller_agent_id', sa.UUID(), nullable=False, comment='调用者 Agent ID'),
sa.Column('callee_agent_id', sa.UUID(), nullable=False, comment='被调用者 Agent ID'),
sa.Column('conversation_id', sa.UUID(), nullable=True, comment='关联会话 ID不使用外键约束避免循环依赖'),
sa.Column('parent_invocation_id', sa.UUID(), nullable=True, comment='父调用 ID用于追踪调用链'),
sa.Column('input_message', sa.Text(), nullable=False, comment='输入消息'),
sa.Column('output_message', sa.Text(), nullable=True, comment='输出消息'),
sa.Column('context', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='上下文信息'),
sa.Column('status', sa.String(length=20), nullable=False, comment='状态: pending|running|completed|failed'),
sa.Column('error_message', sa.Text(), nullable=True, comment='错误信息'),
sa.Column('started_at', sa.DateTime(), nullable=False),
sa.Column('completed_at', sa.DateTime(), nullable=True),
sa.Column('elapsed_time', sa.Float(), nullable=True, comment='耗时(秒)'),
sa.Column('token_usage', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='Token 使用情况'),
sa.Column('meta_data', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='额外元数据'),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(['callee_agent_id'], ['agent_configs.id'], ),
sa.ForeignKeyConstraint(['caller_agent_id'], ['agent_configs.id'], ),
sa.ForeignKeyConstraint(['parent_invocation_id'], ['agent_invocations.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_agent_invocations_callee_agent_id'), 'agent_invocations', ['callee_agent_id'], unique=False)
op.create_index(op.f('ix_agent_invocations_caller_agent_id'), 'agent_invocations', ['caller_agent_id'], unique=False)
op.create_index(op.f('ix_agent_invocations_conversation_id'), 'agent_invocations', ['conversation_id'], unique=False)
op.create_index(op.f('ix_agent_invocations_id'), 'agent_invocations', ['id'], unique=False)
op.create_index(op.f('ix_agent_invocations_parent_invocation_id'), 'agent_invocations', ['parent_invocation_id'], unique=False)
op.create_index(op.f('ix_agent_invocations_started_at'), 'agent_invocations', ['started_at'], unique=False)
op.create_index(op.f('ix_agent_invocations_status'), 'agent_invocations', ['status'], unique=False)
op.create_table('multi_agent_configs',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('app_id', sa.UUID(), nullable=False, comment='关联应用'),
sa.Column('master_agent_id', sa.UUID(), nullable=False, comment='主 Agent ID'),
sa.Column('orchestration_mode', sa.String(length=20), nullable=False, comment='协作模式: sequential|parallel|conditional|loop'),
sa.Column('sub_agents', postgresql.JSON(astext_type=sa.Text()), nullable=False, comment="子 Agent 列表: [{'agent_id': 'uuid', 'name': '...', 'role': '...', 'priority': 1}]"),
sa.Column('routing_rules', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment="路由规则: [{'condition': '...', 'target_agent_id': 'uuid', 'priority': 1}]"),
sa.Column('execution_config', postgresql.JSON(astext_type=sa.Text()), nullable=False, comment="执行配置: {'max_iterations': 5, 'timeout': 60, 'parallel_limit': 3}"),
sa.Column('aggregation_strategy', sa.String(length=20), nullable=False, comment='结果整合策略: merge|vote|priority|custom'),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.ForeignKeyConstraint(['app_id'], ['apps.id'], ),
sa.ForeignKeyConstraint(['master_agent_id'], ['agent_configs.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_multi_agent_configs_app_id'), 'multi_agent_configs', ['app_id'], unique=True)
op.create_index(op.f('ix_multi_agent_configs_id'), 'multi_agent_configs', ['id'], unique=False)
op.add_column('agent_configs', sa.Column('agent_role', sa.String(length=20), nullable=True, comment='Agent 角色: master|sub|standalone'))
op.add_column('agent_configs', sa.Column('agent_domain', sa.String(length=50), nullable=True, comment='专业领域: customer_service|technical_support|sales 等'))
op.add_column('agent_configs', sa.Column('parent_agent_id', sa.UUID(), nullable=True, comment='父 Agent ID'))
op.add_column('agent_configs', sa.Column('capabilities', postgresql.JSON(astext_type=sa.Text()), nullable=True, comment='Agent 能力列表'))
op.create_foreign_key(None, 'agent_configs', 'agent_configs', ['parent_agent_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'agent_configs', type_='foreignkey')
op.drop_column('agent_configs', 'capabilities')
op.drop_column('agent_configs', 'parent_agent_id')
op.drop_column('agent_configs', 'agent_domain')
op.drop_column('agent_configs', 'agent_role')
op.drop_index(op.f('ix_multi_agent_configs_id'), table_name='multi_agent_configs')
op.drop_index(op.f('ix_multi_agent_configs_app_id'), table_name='multi_agent_configs')
op.drop_table('multi_agent_configs')
op.drop_index(op.f('ix_agent_invocations_status'), table_name='agent_invocations')
op.drop_index(op.f('ix_agent_invocations_started_at'), table_name='agent_invocations')
op.drop_index(op.f('ix_agent_invocations_parent_invocation_id'), table_name='agent_invocations')
op.drop_index(op.f('ix_agent_invocations_id'), table_name='agent_invocations')
op.drop_index(op.f('ix_agent_invocations_conversation_id'), table_name='agent_invocations')
op.drop_index(op.f('ix_agent_invocations_caller_agent_id'), table_name='agent_invocations')
op.drop_index(op.f('ix_agent_invocations_callee_agent_id'), table_name='agent_invocations')
op.drop_table('agent_invocations')
# ### end Alembic commands ###