diff --git a/.env b/.env index c79ed9a6..1732d398 100644 --- a/.env +++ b/.env @@ -1,6 +1,6 @@ OPENAI_API_KEY=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 -POSTGRES_CONNECTION_STRING=postgresql://postgres:root@localhost:5432/google-a2a-saas +POSTGRES_CONNECTION_STRING=postgresql://postgres:root@localhost:5432/evo_ai TENANT_ID=45cffb85-51c8-41ed-aa8d-710970a7ce50 KNOWLEDGE_API_URL=http://localhost:5540 diff --git a/requirements.txt b/requirements.txt index 160520f7..b8e1e4cf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ google-cloud-aiplatform python-dotenv google-adk litellm -python-multipart \ No newline at end of file +python-multipart +alembic \ No newline at end of file diff --git a/src/config/database.py b/src/config/database.py index e271f00f..96efda8d 100644 --- a/src/config/database.py +++ b/src/config/database.py @@ -3,9 +3,9 @@ from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from src.config.settings import settings -SQLALCHEMY_DATABASE_URL = settings.POSTGRES_CONNECTION_STRING +POSTGRES_CONNECTION_STRING = settings.POSTGRES_CONNECTION_STRING -engine = create_engine(SQLALCHEMY_DATABASE_URL) +engine = create_engine(POSTGRES_CONNECTION_STRING) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) Base = declarative_base() diff --git a/src/config/settings.py b/src/config/settings.py index 4d5ace35..27684878 100644 --- a/src/config/settings.py +++ b/src/config/settings.py @@ -13,7 +13,7 @@ class Settings(BaseSettings): # Configurações do banco de dados POSTGRES_CONNECTION_STRING: str = os.getenv( "POSTGRES_CONNECTION_STRING", - "postgresql://postgres:root@localhost:5432/google-a2a-saas" + "postgresql://postgres:root@localhost:5432/evo_ai" ) # Configurações do OpenAI diff --git a/src/main.py b/src/main.py index b69cca39..50a3333b 100644 --- a/src/main.py +++ b/src/main.py @@ -26,7 +26,7 @@ app = FastAPI( # Configuração do PostgreSQL POSTGRES_CONNECTION_STRING = os.getenv( "POSTGRES_CONNECTION_STRING", - "postgresql://postgres:root@localhost:5432/google-a2a-saas" + "postgresql://postgres:root@localhost:5432/evo_ai" ) # Criar as tabelas no banco de dados diff --git a/src/models/models.py b/src/models/models.py index de7ed71d..ab431b64 100644 --- a/src/models/models.py +++ b/src/models/models.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, String, UUID, DateTime, ForeignKey, JSON, Text, BigInteger, CheckConstraint +from sqlalchemy import Column, String, UUID, DateTime, ForeignKey, JSON, Text, BigInteger, CheckConstraint, Boolean from sqlalchemy.sql import func from src.config.database import Base import uuid @@ -34,4 +34,31 @@ class Agent(Base): __table_args__ = ( CheckConstraint("type IN ('llm', 'sequential', 'parallel', 'loop')", name='check_agent_type'), - ) \ No newline at end of file + ) + +class MCPServer(Base): + __tablename__ = "mcp_servers" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + name = Column(String, nullable=False) + description = Column(Text, nullable=True) + config_json = Column(JSON, nullable=False, default={}) + environments = Column(JSON, nullable=False, default={}) + type = Column(String, nullable=False, default="official") + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) + + __table_args__ = ( + CheckConstraint("type IN ('official', 'community')", name='check_mcp_server_type'), + ) + +class Tool(Base): + __tablename__ = "tools" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + name = Column(String, nullable=False) + description = Column(Text, nullable=True) + config_json = Column(JSON, nullable=False, default={}) + environments = Column(JSON, nullable=False, default={}) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) \ No newline at end of file diff --git a/src/services/agent_service.py b/src/services/agent_service.py index ee6b9e22..f6ad39ea 100644 --- a/src/services/agent_service.py +++ b/src/services/agent_service.py @@ -1,35 +1,124 @@ from sqlalchemy.orm import Session +from sqlalchemy.exc import SQLAlchemyError +from fastapi import HTTPException, status from src.models.models import Agent from src.schemas.schemas import AgentCreate -from typing import List +from typing import List, Optional import uuid +import logging -def get_agent(db: Session, agent_id: uuid.UUID) -> Agent: - return db.query(Agent).filter(Agent.id == agent_id).first() +logger = logging.getLogger(__name__) -def get_agents_by_client(db: Session, client_id: uuid.UUID, skip: int = 0, limit: int = 100) -> List[Agent]: - return db.query(Agent).filter(Agent.client_id == client_id).offset(skip).limit(limit).all() +def get_agent(db: Session, agent_id: uuid.UUID) -> Optional[Agent]: + """Busca um agente pelo ID""" + try: + agent = db.query(Agent).filter(Agent.id == agent_id).first() + if not agent: + logger.warning(f"Agente não encontrado: {agent_id}") + return None + return agent + except SQLAlchemyError as e: + logger.error(f"Erro ao buscar agente {agent_id}: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Erro ao buscar agente" + ) + +def get_agents_by_client( + db: Session, + client_id: uuid.UUID, + skip: int = 0, + limit: int = 100, + active_only: bool = True +) -> List[Agent]: + """Busca agentes de um cliente com paginação""" + try: + query = db.query(Agent).filter(Agent.client_id == client_id) + + if active_only: + query = query.filter(Agent.is_active == True) + + return query.offset(skip).limit(limit).all() + except SQLAlchemyError as e: + logger.error(f"Erro ao buscar agentes do cliente {client_id}: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Erro ao buscar agentes" + ) def create_agent(db: Session, agent: AgentCreate) -> Agent: - db_agent = Agent(**agent.model_dump()) - db.add(db_agent) - db.commit() - db.refresh(db_agent) - return db_agent - -def update_agent(db: Session, agent_id: uuid.UUID, agent: AgentCreate) -> Agent: - db_agent = db.query(Agent).filter(Agent.id == agent_id).first() - if db_agent: - for key, value in agent.model_dump().items(): - setattr(db_agent, key, value) + """Cria um novo agente""" + try: + db_agent = Agent(**agent.model_dump()) + db.add(db_agent) db.commit() db.refresh(db_agent) - return db_agent + logger.info(f"Agente criado com sucesso: {db_agent.id}") + return db_agent + except SQLAlchemyError as e: + db.rollback() + logger.error(f"Erro ao criar agente: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Erro ao criar agente" + ) + +def update_agent(db: Session, agent_id: uuid.UUID, agent: AgentCreate) -> Optional[Agent]: + """Atualiza um agente existente""" + try: + db_agent = get_agent(db, agent_id) + if not db_agent: + return None + + for key, value in agent.model_dump().items(): + setattr(db_agent, key, value) + + db.commit() + db.refresh(db_agent) + logger.info(f"Agente atualizado com sucesso: {agent_id}") + return db_agent + except SQLAlchemyError as e: + db.rollback() + logger.error(f"Erro ao atualizar agente {agent_id}: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Erro ao atualizar agente" + ) def delete_agent(db: Session, agent_id: uuid.UUID) -> bool: - db_agent = db.query(Agent).filter(Agent.id == agent_id).first() - if db_agent: - db.delete(db_agent) + """Remove um agente (soft delete)""" + try: + db_agent = get_agent(db, agent_id) + if not db_agent: + return False + + db_agent.is_active = False db.commit() + logger.info(f"Agente desativado com sucesso: {agent_id}") return True - return False \ No newline at end of file + except SQLAlchemyError as e: + db.rollback() + logger.error(f"Erro ao desativar agente {agent_id}: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Erro ao desativar agente" + ) + +def activate_agent(db: Session, agent_id: uuid.UUID) -> bool: + """Reativa um agente""" + try: + db_agent = get_agent(db, agent_id) + if not db_agent: + return False + + db_agent.is_active = True + db.commit() + logger.info(f"Agente reativado com sucesso: {agent_id}") + return True + except SQLAlchemyError as e: + db.rollback() + logger.error(f"Erro ao reativar agente {agent_id}: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Erro ao reativar agente" + ) \ No newline at end of file