commit e3ed1a734bb9167451b27f60f68ab1fa42462539 Author: WanderMotta Date: Sun Jan 4 16:14:31 2026 -0300 Commit inicial - upload de todos os arquivos da pasta diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..7fd787c --- /dev/null +++ b/.cursorrules @@ -0,0 +1,231 @@ +# Evo AI - Project Rules and Structure + +## Main Technologies +- FastAPI: Web framework for building the API +- SQLAlchemy: ORM for database interaction +- Alembic: Database migration system +- PostgreSQL: Main database +- Pydantic: Data validation and serialization +- Uvicorn: ASGI server for application execution +- Redis: Cache and session management +- JWT: Secure token authentication +- Bcrypt: Secure password hashing +- SendGrid: Email service for notifications +- Jinja2: Template engine for email rendering + +## Project Structure +``` +src/ +├── api/ +│ ├── __init__.py # Package initialization +│ ├── admin_routes.py # Admin routes for management interface +│ ├── agent_routes.py # Routes to manage agents +│ ├── auth_routes.py # Authentication routes (login, registration) +│ ├── chat_routes.py # Routes for chat interactions with agents +│ ├── client_routes.py # Routes to manage clients +│ ├── mcp_server_routes.py # Routes to manage MCP servers +│ ├── session_routes.py # Routes to manage chat sessions +│ └── tool_routes.py # Routes to manage tools for agents +├── config/ +│ ├── database.py # Database configuration +│ └── settings.py # General settings +├── core/ +│ ├── middleware.py # API Key middleware (legacy) +│ └── jwt_middleware.py # JWT authentication middleware +├── models/ +│ └── models.py # SQLAlchemy models +├── schemas/ +│ ├── schemas.py # Main Pydantic schemas +│ ├── chat.py # Chat schemas +│ ├── user.py # User and authentication schemas +│ └── audit.py # Audit logs schemas +├── services/ +│ ├── agent_service.py # Business logic for agents +│ ├── agent_runner.py # Agent execution logic +│ ├── auth_service.py # JWT authentication logic +│ ├── audit_service.py # Audit logs logic +│ ├── client_service.py # Business logic for clients +│ ├── email_service.py # Email sending service +│ ├── mcp_server_service.py # Business logic for MCP servers +│ ├── session_service.py # Business logic for chat sessions +│ ├── tool_service.py # Business logic for tools +│ └── user_service.py # User management logic +├── templates/ +│ ├── emails/ +│ │ ├── base_email.html # Base template with common structure and styles +│ │ ├── verification_email.html # Email verification template +│ │ ├── password_reset.html # Password reset template +│ │ ├── welcome_email.html # Welcome email after verification +│ │ └── account_locked.html # Security alert for locked accounts +├── tests/ +│ ├── __init__.py # Package initialization +│ ├── api/ +│ │ ├── __init__.py # Package initialization +│ │ ├── test_auth_routes.py # Test for authentication routes +│ │ └── test_root.py # Test for root endpoint +│ ├── models/ +│ │ ├── __init__.py # Package initialization +│ │ ├── test_models.py # Test for models +│ ├── services/ +│ │ ├── __init__.py # Package initialization +│ │ ├── test_auth_service.py # Test for authentication service +│ │ └── test_user_service.py # Test for user service +└── utils/ + ├── logger.py # Logger configuration + └── security.py # Security utilities (JWT, hash) +``` + +## Code Standards + +### Language Requirements +- **ALL code comments, docstrings, and logging messages MUST be written in English** +- Variable names, function names, and class names must be in English +- API error messages must be in English +- Documentation (including inline comments) must be in English +- Code examples in documentation must be in English +- Commit messages must be in English + +### Project Configuration +- Dependencies managed in `pyproject.toml` using modern Python packaging standards +- Development dependencies specified as optional dependencies in `pyproject.toml` +- Single source of truth for project metadata in `pyproject.toml` +- Build system configured to use setuptools +- Pytest configuration in `pyproject.toml` under `[tool.pytest.ini_options]` +- Code formatting with Black configured in `pyproject.toml` +- Linting with Flake8 configured in `.flake8` + +### Schemas (Pydantic) +- Use `BaseModel` as base for all schemas +- Define fields with explicit types +- Use `Optional` for optional fields +- Use `Field` for validations and default values +- Implement `Config` with `from_attributes = True` for models +- Use `EmailStr` for email validation + +### Services +- Error handling with `SQLAlchemyError` +- Consistent logging with messages in English +- Strong typing with `Optional` for null returns +- Documentation with docstrings +- Rollback in case of error +- Standardized returns +- Use transactions for multiple operations + +### Email Templates +- All email templates extend a base template +- Templates written in English +- Use Jinja2 templating system +- Consistent styling using a common base template +- Responsive design for mobile compatibility +- Clear call-to-action buttons +- Fallback mechanisms for failed template rendering + +### Routes +- Appropriate status codes (201 for creation, 204 for deletion) +- Error handling with `HTTPException` +- Error messages in English +- Pagination for list endpoints +- Input validation with schemas +- JWT authentication for all protected routes +- Use of asynchronous functions with `async def` + +### Migrations +- Use Alembic for migration management +- Descriptive names for migrations +- Maintain change history +- Use CASCADE when necessary to remove dependencies + +### Authentication +- Use JWT for authentication with OAuth2PasswordBearer +- JWT tokens with expiration time defined in settings +- Access token containing essential user data (is_admin, client_id, etc.) +- Resource ownership verification based on client_id +- Protection of administrative routes with permission verification +- Email verification system via tokens +- Secure password recovery with one-time tokens +- Account locking after multiple failed login attempts + +### Audit +- Record important administrative actions +- Automatic collection of contextual data (IP, user-agent) +- Relationship with user who performed the action +- Filtering and querying by different criteria + +### Environment Variables +- Use .env file for sensitive settings +- Keep .env.example updated +- Document all environment variables +- Use safe default values +- Validate required variables +- Clear separation between development and production configurations + +## Conventions +- Variable and function names in English +- Log and error messages in English +- Documentation in English +- User-facing content (emails, responses) in English +- Indentation with 4 spaces +- Maximum of 79 characters per line + +## Commit Rules +- Use Conventional Commits format for all commit messages +- Format: `(): ` +- Types: + - `feat`: A new feature + - `fix`: A bug fix + - `docs`: Documentation changes + - `style`: Changes that do not affect code meaning (formatting, etc.) + - `refactor`: Code changes that neither fix a bug nor add a feature + - `perf`: Performance improvements + - `test`: Adding or modifying tests + - `chore`: Changes to build process or auxiliary tools +- Scope is optional and should be the module or component affected +- Description should be concise, in the imperative mood, and not capitalized +- Use body for more detailed explanations if needed +- Reference issues in the footer with `Fixes #123` or `Relates to #123` +- Examples: + - `feat(auth): add password reset functionality` + - `fix(api): correct validation error in client registration` + - `docs: update API documentation for new endpoints` + - `refactor(services): improve error handling in authentication` + +## Best Practices +- Always validate input data +- Implement appropriate logging +- Handle all possible errors +- Maintain consistency in returns +- Document functions and classes +- Follow SOLID principles +- Keep tests updated +- Protect routes with JWT authentication +- Use environment variables for sensitive configurations +- Implement resource ownership verification +- Store passwords only with secure hash (bcrypt) +- Implement appropriate expiration for tokens +- Use template inheritance for consistent email layouts + +## Security +- JWT tokens with limited lifetime +- Email verification with one-time tokens +- Secure password hashing with bcrypt and random salt +- Audit system for administrative actions +- Resource-based access control +- Clear separation between regular users and administrators +- Strict input validation with Pydantic +- Account lockout after multiple failed login attempts + +## Useful Commands +- `make run`: Start the server +- `make run-prod`: Start the server in production mode +- `make alembic-revision message="description"`: Create new migration +- `make alembic-upgrade`: Apply pending migrations +- `make alembic-downgrade`: Revert last migration +- `make alembic-migrate`: Create and apply new migration +- `make alembic-reset`: Reset database to initial state +- `make alembic-upgrade-cascade`: Force upgrade removing dependencies +- `make clear-cache`: Clean project cache +- `make seed-all`: Run all database seeders +- `make lint`: Run linting checks with flake8 +- `make format`: Format code with black +- `make install`: Install project for development +- `make install-dev`: Install project with development dependencies diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6f1b62b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,105 @@ +# Environment and IDE +.venv +venv +.env +.idea +.vscode +__pycache__ +*.pyc +*.pyo +*.pyd +.Python +.pytest_cache +.coverage +htmlcov/ +.tox/ + +# Version control +.git +.github +.gitignore + +# Logs and temp files +logs +*.log +tmp +.DS_Store + +# Docker +.dockerignore +Dockerfile* +docker-compose* + +# Documentation +README.md +LICENSE +docs/ + +# Development tools +tests/ +.flake8 +requirements-dev.txt + +# Python specific - don't exclude frontend +!frontend/ +frontend/node_modules/ +frontend/.next/ +frontend/dist/ + +# Ambiente virtual +venv/ +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +# lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Arquivos específicos do Docker +.dockerignore +Dockerfile +docker-compose.yml + +# Git +.git +.gitignore + +# Logs e dados +logs/ +*.log +data/ + +# Configuração local +.env +.env.local +.env.development +.env.test +.env.production + +# IDEs e editores +.idea/ +.vscode/ +*.swp +*.swo + +# Arquivos de teste +tests/ +test_* +*_test.py + +# Documentação +docs/ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..065cfec --- /dev/null +++ b/.env.example @@ -0,0 +1,72 @@ +API_TITLE="Evo API" +API_DESCRIPTION="API para execução de agentes de IA" +API_VERSION="1.0.0" +API_URL="http://localhost:8000" + +ORGANIZATION_NAME="Evo AI" +ORGANIZATION_URL="https://evoai.evoapicloud.com" + +# AI Engine configuration: "adk" or "crewai" +AI_ENGINE="adk" + +# Database settings +POSTGRES_CONNECTION_STRING="postgresql://postgres:root@localhost:5432/evo_ai" + +# Logging settings +LOG_LEVEL="INFO" +LOG_DIR="logs" + +# Redis settings +REDIS_HOST="localhost" +REDIS_PORT=6379 +REDIS_DB=0 +REDIS_PASSWORD="your-redis-password" +REDIS_SSL=false +REDIS_KEY_PREFIX="a2a:" +REDIS_TTL=3600 + +# Tools cache TTL in seconds (1 hour) +TOOLS_CACHE_TTL=3600 + +# JWT settings +JWT_SECRET_KEY="your-jwt-secret-key" +JWT_ALGORITHM="HS256" +# In seconds +JWT_EXPIRATION_TIME=3600 + +# Encryption key for API keys +ENCRYPTION_KEY="your-encryption-key" + +# Email provider settings +EMAIL_PROVIDER="sendgrid" + +# SendGrid +SENDGRID_API_KEY="your-sendgrid-api-key" +EMAIL_FROM="noreply@yourdomain.com" + +# SMTP settings +SMTP_HOST="your-smtp-host" +SMTP_FROM="noreply-smtp@yourdomain.com" +SMTP_USER="your-smtp-username" +SMTP_PASSWORD="your-smtp-password" +SMTP_PORT=587 +SMTP_USE_TLS=true +SMTP_USE_SSL=false + +APP_URL="https://yourdomain.com" + +LANGFUSE_PUBLIC_KEY="your-langfuse-public-key" +LANGFUSE_SECRET_KEY="your-langfuse-secret-key" +OTEL_EXPORTER_OTLP_ENDPOINT="https://cloud.langfuse.com/api/public/otel" + +# Server settings +HOST="0.0.0.0" +PORT=8000 +DEBUG=false + +# Seeder settings +ADMIN_EMAIL="admin@evoai.com" +ADMIN_INITIAL_PASSWORD="strongpassword123" +DEMO_EMAIL="demo@example.com" +DEMO_PASSWORD="demo123" +DEMO_CLIENT_NAME="Demo Client" diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..ba84055 --- /dev/null +++ b/.flake8 @@ -0,0 +1,8 @@ +[flake8] +max-line-length = 88 +exclude = .git,__pycache__,venv,alembic/versions/* +ignore = E203, W503, E501 +per-file-ignores = + __init__.py: F401 + src/models/models.py: E712 + alembic/*: E711,E712,F401 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7807dc9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,132 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +# lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ +docs/A2A + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# IDE +.idea/ +.vscode/ +*.sublime-project +*.sublime-workspace +.DS_Store + +# Logs +logs/ +*.log + +# Database +*.db +*.sqlite +*.sqlite3 +backup/ + +# Local +local_settings.py +local.py + +# Docker +.docker/ + +# Alembic versions +# alembic/versions/ + +# PyInstaller +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Translations +*.mo +*.pot + +# Django stuff: +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# IDE +*.swp +*.swo + +# OS +Thumbs.db + +uv.lock diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cf0180a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,101 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.0] - 2025-05-24 + +### Added + +- Export and Import Agents + +### Changed + +- A2A implementation updated to version 0.2.1 (https://google.github.io/A2A/specification/#agent2agent-a2a-protocol-specification) +- Frontend redesign +- Fixed message order + +## [0.0.11] - 2025-05-16 + +### Changed + +- Fixes in email service and client service + +## [0.0.10] - 2025-05-15 + +### Added + +- Add Task Agent for structured single-task execution +- Improve context management in agent execution +- Add file support for A2A protocol (Agent-to-Agent) endpoints +- Implement multimodal content processing in A2A messages +- Add SMTP email provider support as alternative to SendGrid + +## [0.0.9] - 2025-05-13 + +### Added + +- Add API key sharing and flexible authentication for chat routes + +### Changed + +- Enhance user authentication with detailed error handling + +## [0.0.8] - 2025-05-13 + +### Changed + +- Update author information in multiple files + +## [0.0.7] - 2025-05-13 + +### Added + +- Docker image CI workflow for automated builds and pushes +- GitHub Container Registry (GHCR) integration +- Automated image tagging based on branch and commit +- Docker Buildx setup for multi-platform builds +- Cache optimization for faster builds +- Automated image publishing on push to main and develop branches + +## [0.0.6] - 2025-05-13 + +### Added + +- Initial public release of Evo AI platform +- FastAPI-based backend API +- JWT authentication with email verification +- Agent management (LLM, A2A, Sequential, Parallel, Loop, Workflow) +- Agent 2 Agent (A2A) protocol support (Google A2A spec) +- MCP server integration and management +- Custom tools management for agents +- Folder-based agent organization +- Secure API key management with encryption +- PostgreSQL and Redis integration +- Email notifications (SendGrid) with Jinja2 templates +- Audit log system for administrative actions +- LangGraph integration for workflow agents +- OpenTelemetry tracing and Langfuse integration +- Docker and Docker Compose support +- English documentation and codebase + +### Changed + +- N/A + +### Fixed + +- N/A + +### Security + +- JWT tokens with expiration and resource-based access control +- Secure password hashing (bcrypt) +- Account lockout after multiple failed login attempts +- Email verification and password reset flows + +--- + +Older versions and future releases will be listed here. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..040fc35 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM python:3.10-slim + +WORKDIR /app + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PYTHONPATH=/app + +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/* + +RUN curl -fsSL https://get.docker.com | bash + +RUN curl -LsSf https://astral.sh/uv/install.sh | sh + +COPY . . + +RUN pip install --no-cache-dir -e . + +ENV PORT=8000 \ + HOST=0.0.0.0 \ + DEBUG=false + +# Expose port +EXPOSE 8000 + +CMD alembic upgrade head && python -m scripts.run_seeders && uvicorn src.main:app --host $HOST --port $PORT \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..727e6b0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2025 Evolution API + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fc6b1f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,86 @@ +.PHONY: migrate init revision upgrade downgrade run seed-admin seed-client seed-mcp-servers seed-tools seed-all docker-build docker-up docker-down docker-logs lint format install install-dev venv + +# Alembic commands +init: + alembic init alembics + +# make alembic-revision message="migration description" +alembic-revision: + alembic revision --autogenerate -m "$(message)" + +# Command to update database to latest version (execute existing migrations) +alembic-upgrade: + alembic upgrade head + +# Command to downgrade one version +alembic-downgrade: + alembic downgrade -1 + +# Command to run the server +run: + uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload --env-file .env --reload-exclude frontend/ --reload-exclude "*.log" --reload-exclude "*.tmp" + +# Command to run the server in production mode +run-prod: + uvicorn src.main:app --host 0.0.0.0 --port 8000 --workers 4 + +# Command to clean cache in all project folders +clear-cache: + rm -rf ~/.cache/uv/environments-v2/* && find . -type d -name "__pycache__" -exec rm -r {} + + +# Command to create a new migration and apply it +alembic-migrate: + alembic revision --autogenerate -m "$(message)" && alembic upgrade head + +# Command to reset the database +alembic-reset: + alembic downgrade base && alembic upgrade head + +# Commands to run seeders +seed-admin: + python -m scripts.seeders.admin_seeder + +seed-client: + python -m scripts.seeders.client_seeder + +seed-mcp-servers: + python -m scripts.seeders.mcp_server_seeder + +seed-tools: + python -m scripts.seeders.tool_seeder + +seed-all: + python -m scripts.run_seeders + +# Docker commands +docker-build: + docker-compose build + +docker-up: + docker-compose up -d + +docker-down: + docker-compose down + +docker-logs: + docker-compose logs -f + +docker-seed: + docker-compose exec api python -m scripts.run_seeders + +# Testing, linting and formatting commands +lint: + flake8 src/ tests/ + +format: + black src/ tests/ + +# Virtual environment and installation commands +venv: + python -m venv venv + +install: + pip install -e . + +install-dev: + pip install -e ".[dev]" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c75cbd6 --- /dev/null +++ b/README.md @@ -0,0 +1,387 @@ +

Evo AI - AI Agents Platform

+ +
+ +[![Whatsapp Group](https://img.shields.io/badge/Group-WhatsApp-%2322BC18)](https://evolution-api.com/whatsapp) +[![Discord Community](https://img.shields.io/badge/Discord-Community-blue)](https://evolution-api.com/discord) +[![Postman Collection](https://img.shields.io/badge/Postman-Collection-orange)](https://evolution-api.com/postman) +[![Documentation](https://img.shields.io/badge/Documentation-Official-green)](https://doc.evolution-api.com) +[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](./LICENSE) +[![Support](https://img.shields.io/badge/Donation-picpay-green)](https://app.picpay.com/user/davidsongomes1998) +[![Sponsors](https://img.shields.io/badge/Github-sponsor-orange)](https://github.com/sponsors/EvolutionAPI) + +
+ +## Evo AI - AI Agents Platform + +Evo AI is an open-source platform for creating and managing AI agents, enabling integration with different AI models and services. + +## 🚀 Overview + +The Evo AI platform allows: + +- Creation and management of AI agents +- Integration with different language models +- Client management and MCP server configuration +- Custom tools management +- **[Google Agent Development Kit (ADK)](https://google.github.io/adk-docs/)**: Base framework for agent development +- **[CrewAI Support](https://github.com/crewAI/crewAI)**: Alternative framework for agent development (in development) +- JWT authentication with email verification +- **[Agent 2 Agent (A2A) Protocol Support](https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/)**: Interoperability between AI agents +- **[Workflow Agent with LangGraph](https://www.langchain.com/langgraph)**: Building complex agent workflows +- **Secure API Key Management**: Encrypted storage of API keys +- **Agent Organization**: Folder structure for organizing agents by categories + +## 🤖 Agent Types + +Evo AI supports different types of agents that can be flexibly combined: + +### 1. LLM Agent (Language Model) + +Agent based on language models like GPT-4, Claude, etc. Can be configured with tools, MCP servers, and sub-agents. + +### 2. A2A Agent (Agent-to-Agent) + +Agent that implements Google's A2A protocol for agent interoperability. + +### 3. Sequential Agent + +Executes a sequence of sub-agents in a specific order. + +### 4. Parallel Agent + +Executes multiple sub-agents simultaneously. + +### 5. Loop Agent + +Executes sub-agents in a loop with a defined maximum number of iterations. + +### 6. Workflow Agent + +Executes sub-agents in a custom workflow defined by a graph structure using LangGraph. + +### 7. Task Agent + +Executes a specific task using a target agent with structured task instructions. + +## 🛠️ Technologies + +### Backend +- **FastAPI**: Web framework for building the API +- **SQLAlchemy**: ORM for database interaction +- **PostgreSQL**: Main database +- **Alembic**: Migration system +- **Pydantic**: Data validation and serialization +- **Uvicorn**: ASGI server +- **Redis**: Cache and session management +- **JWT**: Secure token authentication +- **SendGrid/SMTP**: Email service for notifications (configurable) +- **Jinja2**: Template engine for email rendering +- **Bcrypt**: Password hashing and security +- **LangGraph**: Framework for building stateful, multi-agent workflows + +### Frontend +- **Next.js 15**: React framework with App Router +- **React 18**: User interface library +- **TypeScript**: Type-safe JavaScript +- **Tailwind CSS**: Utility-first CSS framework +- **shadcn/ui**: Modern component library +- **React Hook Form**: Form management +- **Zod**: Schema validation +- **ReactFlow**: Node-based visual workflows +- **React Query**: Server state management + +## 📊 Langfuse Integration (Tracing & Observability) + +Evo AI platform natively supports integration with [Langfuse](https://langfuse.com/) for detailed tracing of agent executions, prompts, model responses, and tool calls, using the OpenTelemetry (OTel) standard. + +### How to configure + +1. **Set environment variables in your `.env`:** + + ```env + LANGFUSE_PUBLIC_KEY="pk-lf-..." + LANGFUSE_SECRET_KEY="sk-lf-..." + OTEL_EXPORTER_OTLP_ENDPOINT="https://cloud.langfuse.com/api/public/otel" + ``` + +2. **View in the Langfuse dashboard** + - Access your Langfuse dashboard to see real-time traces. + +## 🤖 Agent 2 Agent (A2A) Protocol Support + +Evo AI implements the Google's Agent 2 Agent (A2A) protocol, enabling seamless communication and interoperability between AI agents. + +For more information about the A2A protocol, visit [Google's A2A Protocol Documentation](https://google.github.io/A2A/). + +## 📋 Prerequisites + +### Backend +- **Python**: 3.10 or higher +- **PostgreSQL**: 13.0 or higher +- **Redis**: 6.0 or higher +- **Git**: For version control +- **Make**: For running Makefile commands + +### Frontend +- **Node.js**: 18.0 or higher +- **pnpm**: Package manager (recommended) or npm/yarn + +## 🔧 Installation + +### 1. Clone the Repository + +```bash +git clone https://github.com/EvolutionAPI/evo-ai.git +cd evo-ai +``` + +### 2. Backend Setup + +#### Virtual Environment and Dependencies + +```bash +# Create and activate virtual environment +make venv +source venv/bin/activate # Linux/Mac +# or on Windows: venv\Scripts\activate + +# Install development dependencies +make install-dev +``` + +#### Environment Configuration + +```bash +# Copy and configure backend environment +cp .env.example .env +# Edit the .env file with your database, Redis, and other settings +``` + +#### Database Setup + +```bash +# Initialize database and apply migrations +make alembic-upgrade + +# Seed initial data (admin user, sample clients, etc.) +make seed-all +``` + +### 3. Frontend Setup + +#### Install Dependencies + +```bash +# Navigate to frontend directory +cd frontend + +# Install dependencies using pnpm (recommended) +pnpm install + +# Or using npm +# npm install + +# Or using yarn +# yarn install +``` + +#### Frontend Environment Configuration + +```bash +# Copy and configure frontend environment +cp .env.example .env +# Edit .env with your API URL (default: http://localhost:8000) +``` + +The frontend `.env` should contain: + +```env +NEXT_PUBLIC_API_URL=http://localhost:8000 +``` + +## 🚀 Running the Application + +### Development Mode + +#### Start Backend (Terminal 1) +```bash +# From project root +make run +# Backend will be available at http://localhost:8000 +``` + +#### Start Frontend (Terminal 2) +```bash +# From frontend directory +cd frontend +pnpm dev + +# Or using npm/yarn +# npm run dev +# yarn dev + +# Frontend will be available at http://localhost:3000 +``` + +### Production Mode + +#### Backend +```bash +make run-prod # Production with multiple workers +``` + +#### Frontend +```bash +cd frontend +pnpm build && pnpm start + +# Or using npm/yarn +# npm run build && npm start +# yarn build && yarn start +``` + +## 🐳 Docker Installation + +### Full Stack with Docker Compose + +```bash +# Build and start all services (backend + database + redis) +make docker-build +make docker-up + +# Initialize database with seed data +make docker-seed +``` + +### Frontend with Docker + +```bash +# From frontend directory +cd frontend + +# Build frontend image +docker build -t evo-ai-frontend . + +# Run frontend container +docker run -p 3000:3000 -e NEXT_PUBLIC_API_URL=http://localhost:8000 evo-ai-frontend +``` + +Or using the provided docker-compose: + +```bash +# From frontend directory +cd frontend +docker-compose up -d +``` + +## 🎯 Getting Started + +After installation, follow these steps: + +1. **Access the Frontend**: Open `http://localhost:3000` +2. **Create Admin Account**: Use the seeded admin credentials or register a new account +3. **Configure MCP Server**: Set up your first MCP server connection +4. **Create Client**: Add a client to organize your agents +5. **Build Your First Agent**: Create and configure your AI agent +6. **Test Agent**: Use the chat interface to interact with your agent + +### Default Admin Credentials + +After running the seeders, you can login with: +- **Email**: Check the seeder output for the generated admin email +- **Password**: Check the seeder output for the generated password + +## 🖥️ API Documentation + +The interactive API documentation is available at: + +- Swagger UI: `http://localhost:8000/docs` +- ReDoc: `http://localhost:8000/redoc` + +## 👨‍💻 Development Commands + +### Backend Commands +```bash +# Database migrations +make alembic-upgrade # Update database to latest version +make alembic-revision message="description" # Create new migration + +# Seeders +make seed-all # Run all seeders + +# Code verification +make lint # Verify code with flake8 +make format # Format code with black +``` + +### Frontend Commands +```bash +# From frontend directory +cd frontend + +# Development +pnpm dev # Start development server +pnpm build # Build for production +pnpm start # Start production server +pnpm lint # Run ESLint +``` + +## 🚀 Configuration + +### Backend Configuration (.env file) + +Key settings include: + +```bash +# Database settings +POSTGRES_CONNECTION_STRING="postgresql://postgres:root@localhost:5432/evo_ai" + +# Redis settings +REDIS_HOST="localhost" +REDIS_PORT=6379 + +# AI Engine configuration +AI_ENGINE="adk" # Options: "adk" (Google Agent Development Kit) or "crewai" (CrewAI framework) + +# JWT settings +JWT_SECRET_KEY="your-jwt-secret-key" + +# Email provider configuration +EMAIL_PROVIDER="sendgrid" # Options: "sendgrid" or "smtp" + +# Encryption for API keys +ENCRYPTION_KEY="your-encryption-key" +``` + +### Frontend Configuration (.env file) + +```bash +# API Configuration +NEXT_PUBLIC_API_URL="http://localhost:8000" # Backend API URL +``` + +> **Note**: While Google ADK is fully supported, the CrewAI engine option is still under active development. For production environments, it's recommended to use the default "adk" engine. + +## 🔐 Authentication + +The API uses JWT (JSON Web Token) authentication with: + +- User registration and email verification +- Login to obtain JWT tokens +- Password recovery flow +- Account lockout after multiple failed login attempts + +## 🚀 Star Us on GitHub + +If you find EvoAI useful, please consider giving us a star! Your support helps us grow our community and continue improving the product. + +[![Star History Chart](https://api.star-history.com/svg?repos=EvolutionAPI/evo-ai&type=Date)](https://www.star-history.com/#EvolutionAPI/evo-ai&Date) + +## 🤝 Contributing + +We welcome contributions from the community! Please read our [Contributing Guidelines](CONTRIBUTING.md) for more details. + +## 📄 License + +This project is licensed under the [Apache License 2.0](./LICENSE). diff --git a/alembic.ini b/alembic.ini new file mode 100644 index 0000000..f7d32c2 --- /dev/null +++ b/alembic.ini @@ -0,0 +1,119 @@ +# A generic, single database configuration. + +[alembic] +# path to migration scripts +# Use forward slashes (/) also on windows to provide an os agnostic path +script_location = migrations + +# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s +# Uncomment the line below if you want the files to be prepended with date and time +# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file +# for all available tokens +# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s + +# sys.path path, will be prepended to sys.path if present. +# defaults to the current working directory. +prepend_sys_path = . + +# timezone to use when rendering the date within the migration file +# as well as the filename. +# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library. +# Any required deps can installed by adding `alembic[tz]` to the pip requirements +# string value is passed to ZoneInfo() +# leave blank for localtime +# timezone = + +# max length of characters to apply to the "slug" field +# truncate_slug_length = 40 + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +# set to 'true' to allow .pyc and .pyo files without +# a source .py file to be detected as revisions in the +# versions/ directory +# sourceless = false + +# version location specification; This defaults +# to migrations/versions. When using multiple version +# directories, initial revisions must be specified with --version-path. +# The path separator used here should be the separator specified by "version_path_separator" below. +# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions + +# version path separator; As mentioned above, this is the character used to split +# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep. +# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas. +# Valid values for version_path_separator are: +# +# version_path_separator = : +# version_path_separator = ; +# version_path_separator = space +# version_path_separator = newline +# +# Use os.pathsep. Default configuration used for new projects. +version_path_separator = os + +# set to 'true' to search source files recursively +# in each "version_locations" directory +# new in Alembic version 1.10 +# recursive_version_locations = false + +# the output encoding used when revision files +# are written from script.py.mako +# output_encoding = utf-8 + +sqlalchemy.url = postgresql://postgres:root@localhost:5432/evo_ai + + +[post_write_hooks] +# post_write_hooks defines scripts or Python functions that are run +# on newly generated revision scripts. See the documentation for further +# detail and examples + +# format using "black" - use the console_scripts runner, against the "black" entrypoint +# hooks = black +# black.type = console_scripts +# black.entrypoint = black +# black.options = -l 79 REVISION_SCRIPT_FILENAME + +# lint with attempts to fix using "ruff" - use the exec runner, execute a binary +# hooks = ruff +# ruff.type = exec +# ruff.executable = %(here)s/.venv/bin/ruff +# ruff.options = check --fix REVISION_SCRIPT_FILENAME + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARNING +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARNING +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..02462cc --- /dev/null +++ b/conftest.py @@ -0,0 +1,82 @@ +""" +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: conftest.py │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +""" + +import pytest +from fastapi.testclient import TestClient +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.pool import StaticPool + +from src.config.database import Base, get_db +from src.main import app + +# Use in-memory SQLite for tests +SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:" + +engine = create_engine( + SQLALCHEMY_DATABASE_URL, + connect_args={"check_same_thread": False}, + poolclass=StaticPool, +) +TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + + +@pytest.fixture(scope="function") +def db_session(): + """Creates a fresh database session for each test.""" + Base.metadata.create_all(bind=engine) # Create tables + + connection = engine.connect() + transaction = connection.begin() + session = TestingSessionLocal(bind=connection) + + # Use our test database instead of the standard one + def override_get_db(): + try: + yield session + session.commit() + finally: + session.close() + + app.dependency_overrides[get_db] = override_get_db + + yield session # The test will run here + + # Teardown + transaction.rollback() + connection.close() + Base.metadata.drop_all(bind=engine) + app.dependency_overrides.clear() + + +@pytest.fixture(scope="function") +def client(db_session): + """Creates a FastAPI TestClient with database session fixture.""" + with TestClient(app) as test_client: + yield test_client diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..62bba2c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,56 @@ +version: "3.8" + +services: + api: + image: evoapicloud/evo-ai:latest + depends_on: + - postgres + - redis + environment: + POSTGRES_CONNECTION_STRING: postgresql://postgres:${POSTGRES_PASSWORD:-postgres}@postgres:5432/evo_ai + REDIS_HOST: redis + REDIS_PORT: ${REDIS_PORT:-6379} + REDIS_PASSWORD: ${REDIS_PASSWORD:-""} + REDIS_SSL: "false" + REDIS_KEY_PREFIX: "a2a:" + REDIS_TTL: 3600 + JWT_SECRET_KEY: ${JWT_SECRET_KEY} + SENDGRID_API_KEY: ${SENDGRID_API_KEY} + EMAIL_FROM: ${EMAIL_FROM} + APP_URL: https://evo.api.seuadvogadoja.com.br + LOG_LEVEL: INFO + DEBUG: "false" + volumes: + - ./logs:/app/logs + - ./static:/app/static + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/"] + interval: 30s + timeout: 10s + retries: 5 + + postgres: + image: postgres:14-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres} + POSTGRES_DB: evo_ai + volumes: + - postgres_data:/var/lib/postgresql/data + + redis: + image: redis:alpine + command: + - redis-server + - --appendonly + - "yes" + - --requirepass + - "${REDIS_PASSWORD}" + volumes: + - redis_data:/data + +volumes: + postgres_data: + name: evo-ai-postgres-data + redis_data: + name: evo-ai-redis-data diff --git a/docker_build.sh b/docker_build.sh new file mode 100644 index 0000000..1772280 --- /dev/null +++ b/docker_build.sh @@ -0,0 +1,2 @@ +docker build -t atendai/evoai-api:latest . +docker push atendai/evoai-api:latest diff --git a/frontend/.cursorrules b/frontend/.cursorrules new file mode 100644 index 0000000..5d384dd --- /dev/null +++ b/frontend/.cursorrules @@ -0,0 +1,120 @@ +# Next.js Project Rules + +## Language +- All code, comments, documentation, commits, and PRs MUST be written in English. + +## Architecture + +### Folder Structure +- `/app`: App router pages and API routes + - Route-specific components should be placed in their respective route folders +- `/components`: Reusable UI components + - `/ui`: Shadcn UI components and their derivatives +- `/contexts`: React Context providers +- `/hooks`: Custom React hooks +- `/lib`: Utility functions and configuration +- `/public`: Static assets +- `/services`: API service functions +- `/styles`: Global styles +- `/types`: TypeScript type definitions + +### Component Guidelines +- Use functional components with TypeScript +- Use the `.tsx` extension for React components +- Follow a logical naming convention: + - Complex components: Use PascalCase and create folders with an index.tsx file + - Simple components: Single PascalCase named files + +### State Management +- Use React Context for global state +- Use React hooks for local state +- Avoid prop drilling more than 2 levels deep + +### API & Data Fetching +- Use API service modules in `/services` directory +- Implement proper error handling and loading states +- Use React Query or SWR for complex data fetching where appropriate + +## Development Patterns + +### Code Quality +- Maintain type safety - avoid using `any` type +- Write self-documenting code with descriptive names +- Keep components focused on a single responsibility +- Extract complex logic into custom hooks +- Follow DRY (Don't Repeat Yourself) principle + +### CSS & Styling +- Use Tailwind CSS for styling +- Use Shadcn UI components as base building blocks +- Maintain consistent spacing and sizing + +### Performance +- Avoid unnecessary re-renders +- Optimize images and assets +- Implement code splitting where appropriate +- Use dynamic imports for large components/pages + +### Testing +- Write tests for critical business logic +- Test components in isolation +- Implement end-to-end tests for critical user flows + +## Git Workflow + +### Branch Naming +- Features: `feature/short-description` +- Bugfixes: `fix/short-description` +- Hotfixes: `hotfix/short-description` +- Releases: `release/version` + +## Conventions +- Variable and function names in English +- Log and error messages in English +- Documentation in English +- User-facing content (emails, responses) in English +- Indentation with 4 spaces +- Maximum of 79 characters per line + +## Commit Rules +- Use Conventional Commits format for all commit messages +- Format: `(): ` +- Types: + - `feat`: A new feature + - `fix`: A bug fix + - `docs`: Documentation changes + - `style`: Changes that do not affect code meaning (formatting, etc.) + - `refactor`: Code changes that neither fix a bug nor add a feature + - `perf`: Performance improvements + - `test`: Adding or modifying tests + - `chore`: Changes to build process or auxiliary tools +- Scope is optional and should be the module or component affected +- Description should be concise, in the imperative mood, and not capitalized +- Use body for more detailed explanations if needed +- Reference issues in the footer with `Fixes #123` or `Relates to #123` +- Examples: + - `feat(auth): add password reset functionality` + - `fix(api): correct validation error in client registration` + - `docs: update API documentation for new endpoints` + - `refactor(services): improve error handling in authentication` + +Format: `type(scope): subject` + +Examples: +- `feat(auth): add login form validation` +- `fix(api): resolve user data fetching issue` +- `docs(readme): update installation instructions` +- `style(components): format according to style guide` + +### Pull Requests +- Keep PRs focused on a single feature or fix +- Include descriptive titles and descriptions +- Reference related issues +- Request code reviews from appropriate team members +- Ensure CI checks pass before merging + +## Code Review Guidelines +- Focus on code quality, architecture, and maintainability +- Provide constructive feedback +- Address all review comments before merging +- Maintain a respectful and collaborative tone \ No newline at end of file diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 0000000..76b82d9 --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,61 @@ +# Dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Production builds +.next/ +out/ +dist/ + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Logs +logs +*.log + +# Temporary files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# IDEs and editors +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Git +.git +.gitignore + +# Docker +Dockerfile* +docker-compose* +.dockerignore + +# Testing +coverage/ +.nyc_output +.coverage + +# Other +.cache/ \ No newline at end of file diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..f9feddb --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1 @@ +NEXT_PUBLIC_API_URL=http://localhost:8000 \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..400e48e --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,31 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# next.js +/.next/ +/out/ + +# production +/build + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# Lock files +package-lock.json +yarn.lock + +# env files +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/frontend/CHANGELOG.md b/frontend/CHANGELOG.md new file mode 100644 index 0000000..7a1f920 --- /dev/null +++ b/frontend/CHANGELOG.md @@ -0,0 +1,67 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.0.7] - 2025-05-15 + +### Added + +- Add Task agents +- Add file support for A2A protocol (Agent-to-Agent) endpoints +- Add entrypoint script for dynamic environment variable handling +- Add agent card URL input and copy functionality + +## [0.0.6] - 2025-05-13 + +### Added + +- Agent sharing functionality with third parties via API keys +- Dedicated shared-chat page for accessing shared agents +- Local storage mechanism to save recently used shared agents +- Public access to shared agents without full authentication + +### Changed + +- Add example environment file and update .gitignore +- Add clientId prop to agent-related components and improve agent data processing +- Refactor middleware to handle shared agent routes as public paths +- Update API interceptors to prevent forced logout on shared chat pages + +### security + +- Implement force logout functionality on 401 Unauthorized responses + +## [0.0.5] - 2025-05-13 + +### Changed + +- Update author information in multiple files + +## [0.0.4] - 2025-05-13 + +### Added +- Initial public release +- User-friendly interface for creating and managing AI agents +- Integration with multiple language models (e.g., GPT-4, Claude) +- Client management interface +- Visual configuration for MCP servers +- Custom tools management +- JWT authentication with email verification +- Agent 2 Agent (A2A) protocol support (Google's A2A spec) +- Workflow Agent with ReactFlow for visual workflow creation +- Secure API key management (encrypted storage) +- Agent organization with folders and categories +- Dashboard with agent overview, usage stats, and recent activities +- Agent editor for creating, editing, and configuring agents +- Workflow editor for building and visualizing agent flows +- API key manager for adding, encrypting, and rotating keys +- RESTful API and WebSocket backend integration +- Docker support for containerized deployment +- Complete documentation and contribution guidelines + +--- + +Older versions and future releases will be listed here. diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..fee81f4 --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,60 @@ +# Build stage +FROM node:20.15.1-alpine AS builder + +WORKDIR /app + +# Define build arguments with default values +ARG NEXT_PUBLIC_API_URL=https://api.evo-ai.co + +# Install pnpm globally +RUN npm install -g pnpm + +# Copy package files first for better caching +COPY package.json pnpm-lock.yaml ./ + +# Install dependencies +RUN pnpm install --no-frozen-lockfile + +# Copy all source code (this includes tsconfig.json, lib/, etc.) +COPY . . + +# Set environment variables from build arguments +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} + +# Build the application +RUN pnpm run build + +# Production stage +FROM node:20.15.1-alpine AS runner + +WORKDIR /app + +# Define build arguments again for the runner stage +ARG NEXT_PUBLIC_API_URL=https://api-evoai.evoapicloud.com + +# Install pnpm globally +RUN npm install -g pnpm + +# Install production dependencies only +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --prod --no-frozen-lockfile + +# Copy built assets from builder +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder /app/next.config.mjs ./ + +# Set environment variables +ENV NODE_ENV=production +ENV PORT=3000 +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} + +# Script to replace environment variables at runtime +COPY docker-entrypoint.sh ./ +RUN chmod +x ./docker-entrypoint.sh + +# Expose port +EXPOSE 3000 + +# Use entrypoint script to initialize environment variables before starting the app +ENTRYPOINT ["sh", "./docker-entrypoint.sh"] \ No newline at end of file diff --git a/frontend/LICENSE b/frontend/LICENSE new file mode 100644 index 0000000..727e6b0 --- /dev/null +++ b/frontend/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright 2025 Evolution API + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..baf0498 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,237 @@ +# Evo AI - AI Agents Platform (Frontend) + +Evo AI is an open-source platform for creating and managing AI agents, enabling integration with different AI models and services. + +## 🚀 Overview + +The Evo AI frontend platform enables: + +- User-friendly interface for creating and managing AI agents +- Integration with different language models +- Client management +- Visual configuration of MCP servers +- Custom tools management +- JWT authentication with email verification +- **Agent 2 Agent (A2A) Protocol Support**: Interface for interoperability between AI agents following Google's A2A specification +- **Workflow Agent with ReactFlow**: Visual interface for building complex agent workflows +- **Secure API Key Management**: Interface for encrypted storage of API keys +- **Agent Organization**: Folder structure for organizing agents by categories + +## 🧩 Agent Creation Interface + +The frontend offers intuitive interfaces for creating different types of agents: + +### 1. LLM Agent (Language Model) + +Interface for configuring agents based on models like GPT-4, Claude, etc. with tools, MCP servers, and sub-agents. + +### 2. A2A Agent (Agent-to-Agent) + +Interface for implementing Google's A2A protocol for agent interoperability. + +### 3. Sequential Agent + +Interface for executing sub-agents in a specific order. + +### 4. Parallel Agent + +Interface for executing multiple sub-agents simultaneously. + +### 5. Loop Agent + +Interface for executing sub-agents in a loop with a defined number of iterations. + +### 6. Workflow Agent + +Visual interface based on ReactFlow for creating complex workflows between agents. + +## 🛠️ Technologies + +- [Next.js](https://nextjs.org/) - React framework for production +- [React](https://reactjs.org/) - JavaScript library for building user interfaces +- [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS framework +- [Shadcn UI](https://ui.shadcn.com/) - UI component library +- [Radix UI](https://www.radix-ui.com/) - Unstyled, accessible components +- [TypeScript](https://www.typescriptlang.org/) - Typed JavaScript +- [React Query](https://tanstack.com/query/latest) - Data fetching and state management +- [Zustand](https://zustand-demo.pmnd.rs/) - Global state management +- [React Flow](https://reactflow.dev/) - Library for building node-based visual workflows +- [Axios](https://axios-http.com/) - HTTP client for API communication + +## 📋 Requirements + +- Node.js 18+ (LTS recommended) +- npm, yarn, or pnpm package manager +- Evo AI backend running + +## 🔧 Installation + +1. Clone the repository: + +```bash +git clone https://github.com/EvolutionAPI/evo-ai-frontend.git +cd evo-ai-frontend +``` + +2. Install dependencies: + +```bash +npm install +# or +yarn install +# or +pnpm install +``` + +3. Configure environment variables: + +```bash +cp .env.example .env +# Edit the .env file with your settings +``` + +## 🚀 Running the Project + +```bash +# Development mode +npm run dev +# or +yarn dev +# or +pnpm dev + +# Production build +npm run build +# or +yarn build +# or +pnpm build + +# Start production server +npm run start +# or +yarn start +# or +pnpm start +``` + +The project will be available at [http://localhost:3000](http://localhost:3000) + +## 🔐 Authentication + +The frontend implements JWT authentication integrated with the backend: + +- **User Registration**: Form for creating new accounts +- **Email Verification**: Process for verifying via email +- **Login**: Authentication of existing users +- **Password Recovery**: Complete password recovery flow +- **Secure Storage**: Tokens stored in HttpOnly cookies + +## 🖥️ Main Interface Features + +### Dashboard + +Main dashboard showing: +- Agent overview +- Usage statistics +- Recent activities +- Quick links for agent creation + +### Agent Editor + +Complete interface for: +- Creating new agents +- Editing existing agents +- Configuring instructions +- Selecting models +- Setting up API keys + +### Workflow Editor + +Visual editor based on ReactFlow for: +- Creating complex workflows +- Connecting different agents +- Defining conditionals and decision flows +- Visualizing data flow + +### API Key Manager + +Interface for: +- Adding new API keys +- Securely encrypting keys +- Managing existing keys +- Rotating and updating keys + +### Agent Organization + +System for: +- Creating folders and categories +- Organizing agents by type or use case +- Searching and filtering agents + +## 🔄 Backend Integration + +The frontend communicates with the backend through: + +- **RESTful API**: Endpoints for resource management +- **WebSockets**: Real-time communication for agent messages +- **Response Streaming**: Support for streaming model responses + +## 🐳 Docker Support + +The project includes Docker configuration for containerized deployment: + +```bash +# Build the Docker image +./docker_build.sh +# or +docker build -t nextjs-frontend . + +# Run the container +docker run -p 3000:3000 nextjs-frontend +``` + +# 🐳 Docker Compose +```bash +# Copy the .env file +cp .env.example .env + +# Build and deploy + docker-compose up -d --build +``` + +## 🤝 Contributing + +We welcome contributions from the community! Here's how you can help: + +1. Fork the project +2. Create a feature branch (`git checkout -b feature/AmazingFeature`) +3. Make your changes and add tests if possible +4. Run tests and make sure they pass +5. Commit your changes following conventional commits format (`feat: add amazing feature`) +6. Push to the branch (`git push origin feature/AmazingFeature`) +7. Open a Pull Request + +Please read our [Contributing Guidelines](CONTRIBUTING.md) for more details. + +## 📄 License + +This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. + +**Trademark Notice:** The name "Evo AI" and related branding are protected trademarks. Unauthorized use is prohibited. + +## 👨‍💻 Development Commands + +- `npm run dev` - Start the development server +- `npm run build` - Build the application for production +- `npm run start` - Start the production server +- `npm run lint` - Run ESLint to check code quality +- `npm run format` - Format code with Prettier + +## 🙏 Acknowledgments + +- [Next.js](https://nextjs.org/) +- [React](https://reactjs.org/) +- [Tailwind CSS](https://tailwindcss.com/) +- [Shadcn UI](https://ui.shadcn.com/) +- [ReactFlow](https://reactflow.dev/) diff --git a/frontend/app/agents/AgentCard.tsx b/frontend/app/agents/AgentCard.tsx new file mode 100644 index 0000000..75a25cb --- /dev/null +++ b/frontend/app/agents/AgentCard.tsx @@ -0,0 +1,506 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/AgentCard.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Folder } from "@/services/agentService"; +import { Agent, AgentType } from "@/types/agent"; +import { MCPServer } from "@/types/mcpServer"; +import { + ArrowRight, + Bot, + BookOpenCheck, + ChevronDown, + ChevronUp, + Code, + ExternalLink, + GitBranch, + MoveRight, + Pencil, + RefreshCw, + Settings, + Share2, + Trash2, + Workflow, + TextSelect, + Download, + FlaskConical, +} from "lucide-react"; +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { cn } from "@/lib/utils"; +import { exportAsJson } from "@/lib/utils"; + +interface AgentCardProps { + agent: Agent; + onEdit: (agent: Agent) => void; + onDelete: (agent: Agent) => void; + onMove: (agent: Agent) => void; + onShare?: (agent: Agent) => void; + onWorkflow?: (agentId: string) => void; + availableMCPs?: MCPServer[]; + getApiKeyNameById?: (id: string | undefined) => string | null; + getAgentNameById?: (id: string) => string; + folders?: Folder[]; + agents: Agent[]; +} + +export function AgentCard({ + agent, + onEdit, + onDelete, + onMove, + onShare, + onWorkflow, + availableMCPs = [], + getApiKeyNameById = () => null, + getAgentNameById = (id) => id, + folders = [], + agents, +}: AgentCardProps) { + const [expanded, setExpanded] = useState(false); + const router = useRouter(); + + const getAgentTypeInfo = (type: AgentType) => { + const types: Record< + string, + { + label: string; + icon: React.ElementType; + color: string; + bgColor: string; + badgeClass: string; + } + > = { + llm: { + label: "LLM Agent", + icon: Code, + color: "#00cc7d", + bgColor: "bg-green-500/10", + badgeClass: + "bg-green-900/30 text-green-400 border-green-600/30 hover:bg-green-900/40", + }, + a2a: { + label: "A2A Agent", + icon: ExternalLink, + color: "#6366f1", + bgColor: "bg-indigo-500/10", + badgeClass: + "bg-indigo-900/30 text-indigo-400 border-indigo-600/30 hover:bg-indigo-900/40", + }, + sequential: { + label: "Sequential Agent", + icon: ArrowRight, + color: "#f59e0b", + bgColor: "bg-yellow-500/10", + badgeClass: + "bg-yellow-900/30 text-yellow-400 border-yellow-600/30 hover:bg-yellow-900/40", + }, + parallel: { + label: "Parallel Agent", + icon: GitBranch, + color: "#8b5cf6", + bgColor: "bg-purple-500/10", + badgeClass: + "bg-purple-900/30 text-purple-400 border-purple-600/30 hover:bg-purple-900/40", + }, + loop: { + label: "Loop Agent", + icon: RefreshCw, + color: "#ec4899", + bgColor: "bg-pink-500/10", + badgeClass: + "bg-orange-900/30 text-orange-400 border-orange-600/30 hover:bg-orange-900/40", + }, + workflow: { + label: "Workflow Agent", + icon: Workflow, + color: "#3b82f6", + bgColor: "bg-blue-500/10", + badgeClass: + "bg-blue-900/30 text-blue-400 border-blue-700/40 hover:bg-blue-900/40", + }, + task: { + label: "Task Agent", + icon: BookOpenCheck, + color: "#ef4444", + bgColor: "bg-red-500/10", + badgeClass: + "bg-red-900/30 text-red-400 border-red-600/30 hover:bg-red-900/40", + }, + }; + + return ( + types[type] || { + label: type, + icon: Bot, + color: "#94a3b8", + bgColor: "bg-slate-500/10", + badgeClass: + "bg-slate-900/30 text-slate-400 border-slate-600/30 hover:bg-slate-900/40", + } + ); + }; + + const getAgentTypeIcon = (type: AgentType) => { + const typeInfo = getAgentTypeInfo(type); + const IconComponent = typeInfo.icon; + return ( + + ); + }; + + const getAgentTypeName = (type: AgentType) => { + return getAgentTypeInfo(type).label; + }; + + const getAgentTypeBgColor = (type: AgentType) => { + return getAgentTypeInfo(type).bgColor; + }; + + const getAgentTypeBadgeClass = (type: AgentType) => { + return getAgentTypeInfo(type).badgeClass; + }; + + const getFolderNameById = (id: string) => { + const folder = folders?.find((f) => f.id === id); + return folder?.name || id; + }; + + const getTotalTools = () => { + if (agent.type === "llm" && agent.config?.mcp_servers) { + return agent.config.mcp_servers.reduce( + (total, mcp) => total + (mcp.tools?.length || 0), + 0 + ); + } + return 0; + }; + + const getCreatedAtFormatted = () => { + return new Date(agent.created_at).toLocaleDateString(); + }; + + // Function to export the agent as JSON + const handleExportAgent = () => { + try { + exportAsJson( + agent, + `agent-${agent.name + .replace(/\s+/g, "-") + .toLowerCase()}-${agent.id.substring(0, 8)}`, + true, + agents + ); + } catch (error) { + console.error("Error exporting agent:", error); + } + }; + + // Function to test the A2A agent in the lab + const handleTestA2A = () => { + // Use the agent card URL as base for A2A tests + const agentUrl = agent.agent_card_url?.replace( + "/.well-known/agent.json", + "" + ); + + // Use the API key directly from the agent config + const apiKey = agent.config?.api_key; + + // Build the URL with parameters for the lab tests + const params = new URLSearchParams(); + + if (agentUrl) { + params.set("agent_url", agentUrl); + } + + if (apiKey) { + params.set("api_key", apiKey); + } + + // Redirect to the lab tests in the "lab" tab + const testUrl = `/documentation?${params.toString()}#lab`; + + router.push(testUrl); + }; + + return ( + +
+
+ {getAgentTypeIcon(agent.type)} +

{agent.name}

+
+ + {getAgentTypeName(agent.type)} + +
+ + +
+

+ {agent.description && agent.description.length > 100 + ? `${agent.description.substring(0, 100)}...` + : agent.description} +

+
+ +
+
+ Model: + + {agent.type === "llm" ? agent.model : "N/A"} + +
+ +
+ + {expanded && ( +
+ {agent.folder_id && ( +
+ Folder: + + {getFolderNameById(agent.folder_id)} + +
+ )} + + {agent.type === "llm" && agent.api_key_id && ( +
+ API Key: + + {getApiKeyNameById(agent.api_key_id)} + +
+ )} + + {getTotalTools() > 0 && ( +
+ Tools: + {getTotalTools()} +
+ )} + + {agent.config?.sub_agents && agent.config.sub_agents.length > 0 && ( +
+ Sub-agents: + + {agent.config.sub_agents.length} + +
+ )} + + {agent.type === "workflow" && agent.config?.workflow && ( +
+ Elements: + + {agent.config.workflow.nodes?.length || 0} nodes,{" "} + {agent.config.workflow.edges?.length || 0} connections + +
+ )} + +
+ Created at: + {getCreatedAtFormatted()} +
+ +
+ ID: + {agent.id} +
+
+ )} + +
+ + + + + + + + Test A2A + + onEdit(agent)} + > + + Edit Agent + + onMove(agent)} + > + + Move Agent + + {onWorkflow && agent.type === "workflow" && ( + onWorkflow(agent.id)} + > + + Open Workflow + + )} + + + Export as JSON + + {onShare && ( + onShare(agent)} + > + + Share Agent + + )} + onDelete(agent)} + > + + Delete Agent + + + + + + + ); +} diff --git a/frontend/app/agents/AgentList.tsx b/frontend/app/agents/AgentList.tsx new file mode 100644 index 0000000..6eb55af --- /dev/null +++ b/frontend/app/agents/AgentList.tsx @@ -0,0 +1,130 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/AgentList.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { Agent } from "@/types/agent"; +import { MCPServer } from "@/types/mcpServer"; +import { AgentCard } from "./AgentCard"; +import { EmptyState } from "./EmptyState"; +import { ApiKey, Folder } from "@/services/agentService"; + +interface AgentListProps { + agents: Agent[]; + isLoading: boolean; + searchTerm: string; + selectedFolderId: string | null; + availableMCPs: MCPServer[]; + getApiKeyNameById: (id: string | undefined) => string | null; + getAgentNameById: (id: string) => string; + onEdit: (agent: Agent) => void; + onDelete: (agent: Agent) => void; + onMove: (agent: Agent) => void; + onShare?: (agent: Agent) => void; + onWorkflow?: (agentId: string) => void; + onClearSearch?: () => void; + onCreateAgent?: () => void; + apiKeys: ApiKey[]; + folders: Folder[]; +} + +export function AgentList({ + agents, + isLoading, + searchTerm, + selectedFolderId, + availableMCPs, + getApiKeyNameById, + getAgentNameById, + onEdit, + onDelete, + onMove, + onShare, + onWorkflow, + onClearSearch, + onCreateAgent, + apiKeys, + folders, +}: AgentListProps) { + if (isLoading) { + return ( +
+
+
+ ); + } + + if (agents.length === 0) { + if (searchTerm) { + return ( + + ); + } else if (selectedFolderId) { + return ( + + ); + } else { + return ( + + ); + } + } + + return ( +
+ {agents.map((agent) => ( + + ))} +
+ ); +} diff --git a/frontend/app/agents/AgentSidebar.tsx b/frontend/app/agents/AgentSidebar.tsx new file mode 100644 index 0000000..1635810 --- /dev/null +++ b/frontend/app/agents/AgentSidebar.tsx @@ -0,0 +1,186 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/AgentSidebar.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + Folder, + FolderPlus, + Home, + X, + CircleEllipsis, + Edit, + Trash2, +} from "lucide-react"; + +interface AgentFolder { + id: string; + name: string; + description: string; +} + +interface AgentSidebarProps { + visible: boolean; + folders: AgentFolder[]; + selectedFolderId: string | null; + onSelectFolder: (id: string | null) => void; + onAddFolder: () => void; + onEditFolder: (folder: AgentFolder) => void; + onDeleteFolder: (folder: AgentFolder) => void; + onClose: () => void; +} + +export function AgentSidebar({ + visible, + folders, + selectedFolderId, + onSelectFolder, + onAddFolder, + onEditFolder, + onDeleteFolder, + onClose, +}: AgentSidebarProps) { + return ( + <> + {visible && ( + + )} + +
+
+

+ + Folders +

+
+ + +
+
+ +
+ + + {folders.map((folder) => ( +
+ + +
+ + + + + + { + e.stopPropagation(); + onEditFolder(folder); + }} + > + + Edit + + { + e.stopPropagation(); + onDeleteFolder(folder); + }} + > + + Delete + + + +
+
+ ))} +
+
+ + ); +} diff --git a/frontend/app/agents/AgentTypeSelector.tsx b/frontend/app/agents/AgentTypeSelector.tsx new file mode 100644 index 0000000..35db3de --- /dev/null +++ b/frontend/app/agents/AgentTypeSelector.tsx @@ -0,0 +1,96 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/AgentTypeSelector.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { AgentType } from "@/types/agent"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Code, + ExternalLink, + GitBranch, + RefreshCw, + Workflow, + Users, + BookOpenCheck, +} from "lucide-react"; + +interface AgentTypeSelectorProps { + value: AgentType; + onValueChange: (value: AgentType) => void; + className?: string; +} + +export const agentTypes = [ + { value: "llm", label: "LLM Agent", icon: Code }, + { value: "a2a", label: "A2A Agent", icon: ExternalLink }, + { value: "sequential", label: "Sequential Agent", icon: Workflow }, + { value: "parallel", label: "Parallel Agent", icon: GitBranch }, + { value: "loop", label: "Loop Agent", icon: RefreshCw }, + { value: "workflow", label: "Workflow Agent", icon: Workflow }, + { value: "task", label: "Task Agent", icon: BookOpenCheck }, +]; + +export function AgentTypeSelector({ + value, + onValueChange, + className = "", +}: AgentTypeSelectorProps) { + return ( + + ); +} diff --git a/frontend/app/agents/EmptyState.tsx b/frontend/app/agents/EmptyState.tsx new file mode 100644 index 0000000..b084c01 --- /dev/null +++ b/frontend/app/agents/EmptyState.tsx @@ -0,0 +1,107 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/EmptyState.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { Button } from "@/components/ui/button"; +import { Folder, Plus, Search, Server } from "lucide-react"; + +interface EmptyStateProps { + type: "no-agents" | "empty-folder" | "search-no-results"; + searchTerm?: string; + onAction?: () => void; + actionLabel?: string; +} + +export function EmptyState({ + type, + searchTerm = "", + onAction, + actionLabel = "Create Agent", +}: EmptyStateProps) { + const getIcon = () => { + switch (type) { + case "empty-folder": + return ; + case "search-no-results": + return ; + case "no-agents": + default: + return ; + } + }; + + const getTitle = () => { + switch (type) { + case "empty-folder": + return "Empty folder"; + case "search-no-results": + return "No agents found"; + case "no-agents": + default: + return "No agents found"; + } + }; + + const getMessage = () => { + switch (type) { + case "empty-folder": + return "This folder is empty. Add agents or create a new one."; + case "search-no-results": + return `We couldn't find any agents that match your search: "${searchTerm}"`; + case "no-agents": + default: + return "You don't have any agents configured. Create your first agent to start!"; + } + }; + + return ( +
+
+ {getIcon()} +
+

{getTitle()}

+

{getMessage()}

+ {onAction && ( + + )} +
+ ); +} diff --git a/frontend/app/agents/SearchInput.tsx b/frontend/app/agents/SearchInput.tsx new file mode 100644 index 0000000..f8e3073 --- /dev/null +++ b/frontend/app/agents/SearchInput.tsx @@ -0,0 +1,153 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/SearchInput.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { useState } from "react"; +import { Input } from "@/components/ui/input"; +import { Search, X, Filter } from "lucide-react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Button } from "@/components/ui/button"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; + +interface SearchInputProps { + value: string; + onChange: (value: string) => void; + placeholder?: string; + className?: string; + selectedAgentType?: string | null; + onAgentTypeChange?: (type: string | null) => void; + agentTypes?: string[]; +} + +// Using "all" as a special value to represent no filter +const ANY_TYPE_VALUE = "all"; + +export function SearchInput({ + value, + onChange, + placeholder = "Search agents...", + className = "", + selectedAgentType = null, + onAgentTypeChange, + agentTypes = [], +}: SearchInputProps) { + const [isFilterOpen, setIsFilterOpen] = useState(false); + + const handleTypeChange = (value: string) => { + if (onAgentTypeChange) { + onAgentTypeChange(value === ANY_TYPE_VALUE ? null : value); + } + }; + + return ( +
+
+ + onChange(e.target.value)} + autoComplete="off" + className="pl-10 w-full bg-[#222] border-[#444] text-white focus:border-emerald-400 focus:ring-emerald-400/10" + /> + {value && ( + + )} +
+ + {agentTypes.length > 0 && onAgentTypeChange && ( + + + + + +
+
+ Filter by type +
+ + + {selectedAgentType && ( + + )} +
+
+
+ )} +
+ ); +} diff --git a/frontend/app/agents/config/A2AAgentConfig.tsx b/frontend/app/agents/config/A2AAgentConfig.tsx new file mode 100644 index 0000000..99f6a5d --- /dev/null +++ b/frontend/app/agents/config/A2AAgentConfig.tsx @@ -0,0 +1,73 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/config/A2AAgentConfig.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; + +interface A2AAgentConfigProps { + values: { + agent_card_url?: string; + }; + onChange: (values: any) => void; +} + +export function A2AAgentConfig({ values, onChange }: A2AAgentConfigProps) { + return ( +
+
+ + + onChange({ + ...values, + agent_card_url: e.target.value, + }) + } + placeholder="https://example.com/.well-known/agent-card.json" + className="col-span-3 bg-[#222] border-[#444] text-white" + /> +
+
+

+ Provide the full URL for the JSON file of the Agent Card that describes + this agent. +

+

+ Agent Cards contain metadata, capabilities descriptions and supported + protocols. +

+
+
+ ); +} diff --git a/frontend/app/agents/config/LLMAgentConfig.tsx b/frontend/app/agents/config/LLMAgentConfig.tsx new file mode 100644 index 0000000..9c3d144 --- /dev/null +++ b/frontend/app/agents/config/LLMAgentConfig.tsx @@ -0,0 +1,367 @@ +/* +┌──────────────────────────────────────────────────────────────────────────────┐ +│ @author: Davidson Gomes │ +│ @file: /app/agents/config/LLMAgentConfig.tsx │ +│ Developed by: Davidson Gomes │ +│ Creation date: May 13, 2025 │ +│ Contact: contato@evolution-api.com │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @copyright © Evolution API 2025. All rights reserved. │ +│ Licensed under the Apache License, Version 2.0 │ +│ │ +│ You may not use this file except in compliance with the License. │ +│ You may obtain a copy of the License at │ +│ │ +│ http://www.apache.org/licenses/LICENSE-2.0 │ +│ │ +│ Unless required by applicable law or agreed to in writing, software │ +│ distributed under the License is distributed on an "AS IS" BASIS, │ +│ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. │ +│ See the License for the specific language governing permissions and │ +│ limitations under the License. │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ @important │ +│ For any future changes to the code in this file, it is recommended to │ +│ include, together with the modification, the information of the developer │ +│ who changed it and the date of modification. │ +└──────────────────────────────────────────────────────────────────────────────┘ +*/ +"use client"; + +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Textarea } from "@/components/ui/textarea"; +import { ApiKey } from "@/services/agentService"; +import { Plus, Maximize2, Save } from "lucide-react"; +import { useEffect, useState } from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; + +interface ModelOption { + value: string; + label: string; + provider: string; +} + +interface LLMAgentConfigProps { + apiKeys: ApiKey[]; + availableModels: ModelOption[]; + values: { + model?: string; + api_key_id?: string; + instruction?: string; + role?: string; + goal?: string; + }; + onChange: (values: any) => void; + onOpenApiKeysDialog: () => void; +} + +export function LLMAgentConfig({ + apiKeys, + availableModels, + values, + onChange, + onOpenApiKeysDialog, +}: LLMAgentConfigProps) { + const [instructionText, setInstructionText] = useState(values.instruction || ""); + const [isInstructionModalOpen, setIsInstructionModalOpen] = useState(false); + const [expandedInstructionText, setExpandedInstructionText] = useState(""); + + useEffect(() => { + setInstructionText(values.instruction || ""); + }, [values.instruction]); + + const handleInstructionChange = (e: React.ChangeEvent) => { + const newValue = e.target.value; + setInstructionText(newValue); + + onChange({ + ...values, + instruction: newValue, + }); + }; + + const handleExpandInstruction = () => { + setExpandedInstructionText(instructionText); + setIsInstructionModalOpen(true); + }; + + const handleSaveExpandedInstruction = () => { + setInstructionText(expandedInstructionText); + onChange({ + ...values, + instruction: expandedInstructionText, + }); + setIsInstructionModalOpen(false); + }; + + return ( +
+
+ +
+ + onChange({ + ...values, + role: e.target.value, + }) + } + placeholder="Ex: Research Assistant, Customer Support, etc." + className="bg-[#222] border-[#444] text-white" + /> +
+ ℹ️ + Define the role or persona that the agent will assume +
+
+
+ +
+ +
+ + onChange({ + ...values, + goal: e.target.value, + }) + } + placeholder="Ex: Find and organize information, Assist customers with inquiries, etc." + className="bg-[#222] border-[#444] text-white" + /> +
+ ℹ️ + Define the main objective or purpose of this agent +
+
+
+ +
+ +
+
+ + + +
+ + {apiKeys.length === 0 && ( +
+ i + + You need to{" "} + {" "} + before creating an agent. + +
+ )} +
+
+ +
+ + { + const searchQuery = e.target.value.toLowerCase(); + const items = document.querySelectorAll('[data-model-item="true"]'); + items.forEach((item) => { + const text = item.textContent?.toLowerCase() || ''; + if (text.includes(searchQuery)) { + (item as HTMLElement).style.display = 'flex'; + } else { + (item as HTMLElement).style.display = 'none'; + } + }); + }} + /> +
+
+ {availableModels + .filter((model) => { + if (!values.api_key_id) return true; + + const selectedKey = apiKeys.find( + (key) => key.id === values.api_key_id + ); + + if (!selectedKey) return true; + + return model.provider === selectedKey.provider; + }) + .map((model) => ( + + {model.label} + + ))} +
+ + +
+ +
+ +
+
+