From 0e90c811f852225c29ee5379ed31489ed18dd064 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Mon, 5 May 2025 16:37:21 -0300 Subject: [PATCH] refactor(docker): update .dockerignore and Dockerfile for improved build process --- .dockerignore | 3 +- .env | 2 ++ Dockerfile | 14 ++++---- migrations/env.py | 19 ++++++++--- src/api/chat_routes.py | 2 +- src/main.py | 1 + src/services/agent_service.py | 58 +++++++++++++++++---------------- src/services/email_service.py | 2 +- src/services/session_service.py | 1 - 9 files changed, 57 insertions(+), 45 deletions(-) diff --git a/.dockerignore b/.dockerignore index 3bd4b3f1..452279c2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -38,7 +38,6 @@ docs/ # Development tools tests/ .flake8 -pyproject.toml requirements-dev.txt Makefile @@ -98,4 +97,4 @@ test_* *_test.py # Documentação -docs/ \ No newline at end of file +docs/ diff --git a/.env b/.env index d0882bd4..3c62fc04 100644 --- a/.env +++ b/.env @@ -46,3 +46,5 @@ ADMIN_INITIAL_PASSWORD="senhaforte123" DEMO_EMAIL="demo@exemplo.com" DEMO_PASSWORD="demo123" DEMO_CLIENT_NAME="Cliente Demo" + +# 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 diff --git a/Dockerfile b/Dockerfile index f56e756e..2157b466 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,28 @@ FROM python:3.10-slim -# Define o diretório de trabalho WORKDIR /app -# Define variáveis de ambiente ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PYTHONPATH=/app -# Instala as dependências do sistema RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ libpq-dev \ + curl \ + gnupg \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y nodejs \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* -# Copy project files COPY . . -# Install dependencies RUN pip install --no-cache-dir -e . -# Configuração para produção ENV PORT=8000 \ HOST=0.0.0.0 \ DEBUG=false @@ -29,5 +30,4 @@ ENV PORT=8000 \ # Expose port EXPOSE 8000 -# Define o comando de inicialização CMD alembic upgrade head && uvicorn src.main:app --host $HOST --port $PORT \ No newline at end of file diff --git a/migrations/env.py b/migrations/env.py index 58e850ce..4ed2267d 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -10,11 +10,15 @@ from sqlalchemy.ext.asyncio import AsyncEngine from alembic import context from src.models.models import Base +from src.config.settings import settings # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config +# Sobrescreve a URL do banco de dados com a definida nas configurações +config.set_main_option("sqlalchemy.url", settings.POSTGRES_CONNECTION_STRING) + # Interpret the config file for Python logging. # This line sets up loggers basically. if config.config_file_name is not None: @@ -32,7 +36,8 @@ target_metadata = [Base.metadata] # ... etc. # Lista de tabelas a serem ignoradas na geração automática de migrações -exclude_tables = ['sessions', 'events', 'app_states', 'user_states'] +exclude_tables = ["sessions", "events", "app_states", "user_states"] + def include_object(object, name, type_, reflected, compare_to): """ @@ -78,11 +83,13 @@ def run_migrations_online() -> None: connectable = context.config.attributes.get("connection", None) if connectable is None: connectable = create_async_engine( - context.config.get_main_option("sqlalchemy.url").replace("postgresql://", "postgresql+asyncpg://"), - poolclass=pool.NullPool, - future=True, + context.config.get_main_option("sqlalchemy.url").replace( + "postgresql://", "postgresql+asyncpg://" + ), + poolclass=pool.NullPool, + future=True, ) - + if isinstance(connectable, AsyncEngine): asyncio.run(run_async_migrations(connectable)) else: @@ -94,6 +101,7 @@ async def run_async_migrations(connectable): await connection.run_sync(do_run_migrations) await connectable.dispose() + def do_run_migrations(connection): context.configure( connection=connection, @@ -104,4 +112,5 @@ def do_run_migrations(connection): with context.begin_transaction(): context.run_migrations() + run_migrations_online() diff --git a/src/api/chat_routes.py b/src/api/chat_routes.py index 3a282d7e..c728de65 100644 --- a/src/api/chat_routes.py +++ b/src/api/chat_routes.py @@ -136,7 +136,7 @@ async def websocket_chat( @router.post( - "/", + "", response_model=ChatResponse, responses={ 400: {"model": ErrorResponse}, diff --git a/src/main.py b/src/main.py index 327b6ec8..3a6b656a 100644 --- a/src/main.py +++ b/src/main.py @@ -36,6 +36,7 @@ app = FastAPI( title=settings.API_TITLE, description=settings.API_DESCRIPTION, version=settings.API_VERSION, + redirect_slashes=False, ) # CORS configuration diff --git a/src/services/agent_service.py b/src/services/agent_service.py index 07df77b8..07f4fd64 100644 --- a/src/services/agent_service.py +++ b/src/services/agent_service.py @@ -37,24 +37,24 @@ def _convert_uuid_to_str(obj): def validate_sub_agents(db: Session, sub_agents: List[Union[uuid.UUID, str]]) -> bool: """Validate if all sub-agents exist""" - logger.info(f"Validando sub-agentes: {sub_agents}") + logger.info(f"Validating sub-agents: {sub_agents}") if not sub_agents: - logger.warning("Lista de sub-agentes vazia") + logger.warning("Empty sub-agents list") return False for agent_id in sub_agents: - # Garantir que o ID esteja no formato correto + # Ensure the ID is in the correct format agent_id_str = str(agent_id) - logger.info(f"Validando sub-agente com ID: {agent_id_str}") + logger.info(f"Validating sub-agent with ID: {agent_id_str}") agent = get_agent(db, agent_id_str) if not agent: - logger.warning(f"Sub-agente não encontrado: {agent_id_str}") + logger.warning(f"Sub-agent not found: {agent_id_str}") return False - logger.info(f"Sub-agente válido: {agent.name} (ID: {agent_id_str})") + logger.info(f"Valid sub-agent: {agent.name} (ID: {agent_id_str})") - logger.info(f"Todos os {len(sub_agents)} sub-agentes são válidos") + logger.info(f"All {len(sub_agents)} sub-agents are valid") return True @@ -147,29 +147,31 @@ async def create_agent(db: Session, agent: AgentCreate) -> Agent: detail=f"Failed to process agent card: {str(e)}", ) - if not isinstance(agent.config, dict): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Invalid configuration: must be an object with sub_agents", - ) + # Additional sub-agent validation (for non-llm and non-a2a types) + elif agent.type != "llm": + if not isinstance(agent.config, dict): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid configuration: must be an object with sub_agents", + ) - if "sub_agents" not in agent.config: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Invalid configuration: sub_agents is required for sequential, parallel or loop agents", - ) + if "sub_agents" not in agent.config: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid configuration: sub_agents is required for sequential, parallel or loop agents", + ) - if not agent.config["sub_agents"]: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Invalid configuration: sub_agents cannot be empty", - ) + if not agent.config["sub_agents"]: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid configuration: sub_agents cannot be empty", + ) - if not validate_sub_agents(db, agent.config["sub_agents"]): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="One or more sub-agents do not exist", - ) + if not validate_sub_agents(db, agent.config["sub_agents"]): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="One or more sub-agents do not exist", + ) # Process the configuration before creating the agent config = agent.config @@ -225,7 +227,7 @@ async def create_agent(db: Session, agent: AgentCreate) -> Agent: # Generate automatic API key if not provided or empty if not config.get("api_key") or config.get("api_key") == "": - logger.info(f"Generating automatic API key for new agent") + logger.info("Generating automatic API key for new agent") config["api_key"] = generate_api_key() agent.config = config diff --git a/src/services/email_service.py b/src/services/email_service.py index 6544908f..9ea5bd04 100644 --- a/src/services/email_service.py +++ b/src/services/email_service.py @@ -56,7 +56,7 @@ def send_verification_email(email: str, token: str) -> bool: to_email = To(email) subject = "Email Verification - Evo AI" - verification_link = f"{settings.APP_URL}/auth/verify-email/{token}" + verification_link = f"{settings.APP_URL}/api/v1/auth/verify-email/{token}" html_content = _render_template( "verification_email", diff --git a/src/services/session_service.py b/src/services/session_service.py index 1b394d44..d040c2db 100644 --- a/src/services/session_service.py +++ b/src/services/session_service.py @@ -11,7 +11,6 @@ from src.services.agent_service import get_agents_by_client import uuid import logging -from datetime import datetime logger = logging.getLogger(__name__)