From 956d16a854aef845d04fe9752cd10553a135e789 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Sat, 24 May 2025 09:51:34 -0300 Subject: [PATCH] feat(frontend): add initial frontend structure with components, services, and assets --- frontend/.cursorrules | 120 + frontend/.env.example | 1 + frontend/.github/workflows/docker-image.yml | 48 + .../publish_docker_image_homolog.yml | 48 + .../workflows/publish_docker_image_latest.yml | 48 + frontend/.gitignore | 31 + frontend/CHANGELOG.md | 67 + frontend/Dockerfile | 63 + frontend/LICENSE | 201 + frontend/README.md | 237 + frontend/app/agents/AgentCard.tsx | 506 ++ frontend/app/agents/AgentList.tsx | 130 + frontend/app/agents/AgentSidebar.tsx | 186 + frontend/app/agents/AgentTypeSelector.tsx | 96 + frontend/app/agents/EmptyState.tsx | 107 + frontend/app/agents/SearchInput.tsx | 153 + frontend/app/agents/config/A2AAgentConfig.tsx | 73 + frontend/app/agents/config/LLMAgentConfig.tsx | 367 ++ .../agents/config/LoopAgentConfig copy.tsx | 133 + .../app/agents/config/ParallelAgentConfig.tsx | 125 + .../agents/config/SequentialAgentConfig.tsx | 120 + .../app/agents/config/TaskAgentConfig.tsx | 801 +++ .../app/agents/dialogs/AgentToolDialog.tsx | 184 + frontend/app/agents/dialogs/ApiKeysDialog.tsx | 445 ++ .../app/agents/dialogs/ConfirmationDialog.tsx | 93 + .../app/agents/dialogs/CustomMCPDialog.tsx | 237 + .../app/agents/dialogs/CustomToolDialog.tsx | 864 +++ frontend/app/agents/dialogs/FolderDialog.tsx | 158 + .../app/agents/dialogs/ImportAgentDialog.tsx | 239 + frontend/app/agents/dialogs/MCPDialog.tsx | 278 + .../app/agents/dialogs/MoveAgentDialog.tsx | 136 + .../app/agents/dialogs/ShareAgentDialog.tsx | 172 + frontend/app/agents/forms/AgentForm.tsx | 331 + frontend/app/agents/forms/BasicInfoTab.tsx | 243 + .../app/agents/forms/ConfigurationTab.tsx | 722 +++ frontend/app/agents/forms/SubAgentsTab.tsx | 246 + frontend/app/agents/page.tsx | 754 +++ frontend/app/agents/workflows/Canva.tsx | 689 ++ frontend/app/agents/workflows/ContextMenu.tsx | 118 + frontend/app/agents/workflows/HelperLines.tsx | 98 + frontend/app/agents/workflows/NodePanel.tsx | 273 + frontend/app/agents/workflows/canva.css | 188 + .../agents/workflows/edges/DefaultEdge.tsx | 119 + frontend/app/agents/workflows/edges/index.ts | 41 + .../app/agents/workflows/nodes/BaseNode.tsx | 166 + .../components/agent/AgentChatMessageList.tsx | 347 + .../nodes/components/agent/AgentForm.tsx | 631 ++ .../nodes/components/agent/AgentNode.tsx | 176 + .../components/agent/AgentTestChatModal.tsx | 470 ++ .../nodes/components/agent/styles.css | 68 + .../components/condition/ConditionDialog.tsx | 283 + .../components/condition/ConditionForm.tsx | 290 + .../components/condition/ConditionNode.tsx | 204 + .../nodes/components/delay/DelayForm.tsx | 256 + .../nodes/components/delay/DelayNode.tsx | 146 + .../nodes/components/message/MessageForm.tsx | 292 + .../nodes/components/message/MessageNode.tsx | 162 + .../nodes/components/start/StartNode.tsx | 100 + frontend/app/agents/workflows/nodes/index.ts | 109 + .../agents/workflows/nodes/nodeFunctions.ts | 65 + frontend/app/agents/workflows/nodes/style.css | 54 + frontend/app/agents/workflows/page.tsx | 218 + frontend/app/agents/workflows/utils.ts | 199 + .../app/chat/components/AgentInfoDialog.tsx | 497 ++ .../app/chat/components/AttachedFiles.tsx | 158 + .../app/chat/components/ChatContainer.tsx | 190 + frontend/app/chat/components/ChatInput.tsx | 270 + frontend/app/chat/components/ChatMessage.tsx | 375 ++ frontend/app/chat/components/FileUpload.tsx | 185 + .../chat/components/InlineDataAttachments.tsx | 182 + frontend/app/chat/components/SessionList.tsx | 248 + frontend/app/chat/page.tsx | 881 +++ frontend/app/client-layout.tsx | 52 + frontend/app/clients/loading.tsx | 31 + frontend/app/clients/page.tsx | 462 ++ .../components/A2AComplianceCard.tsx | 333 + .../documentation/components/CodeBlock.tsx | 78 + .../components/CodeExamplesSection.tsx | 317 + .../components/DocumentationSection.tsx | 588 ++ .../FrontendImplementationSection.tsx | 796 +++ .../documentation/components/HttpLabForm.tsx | 523 ++ .../documentation/components/LabSection.tsx | 185 + .../components/QuickStartTemplates.tsx | 179 + .../components/StreamLabForm.tsx | 366 ++ .../components/TechnicalDetailsSection.tsx | 470 ++ frontend/app/documentation/page.tsx | 1611 +++++ frontend/app/globals.css | 87 + frontend/app/layout.tsx | 73 + frontend/app/login/page.tsx | 556 ++ frontend/app/logout/page.tsx | 75 + frontend/app/mcp-servers/loading.tsx | 31 + frontend/app/mcp-servers/page.tsx | 940 +++ frontend/app/page.tsx | 33 + frontend/app/profile/page.tsx | 190 + frontend/app/security/page.tsx | 163 + frontend/app/security/reset-password/page.tsx | 198 + frontend/app/security/verify-email/page.tsx | 119 + frontend/app/shared-chat/AgentInfo.tsx | 302 + .../components/SharedChatPanel.tsx | 180 + .../components/SharedSessionList.tsx | 204 + frontend/app/shared-chat/page.tsx | 717 ++ frontend/components.json | 21 + frontend/components/ImpersonationBar.tsx | 129 + frontend/components/sidebar.tsx | 357 + frontend/components/theme-provider.tsx | 39 + frontend/components/toaster.tsx | 52 + frontend/components/ui/accordion.tsx | 58 + frontend/components/ui/alert-dialog.tsx | 141 + frontend/components/ui/alert.tsx | 59 + frontend/components/ui/aspect-ratio.tsx | 7 + frontend/components/ui/avatar.tsx | 50 + frontend/components/ui/badge.tsx | 29 + frontend/components/ui/breadcrumb.tsx | 115 + frontend/components/ui/button.tsx | 56 + frontend/components/ui/calendar.tsx | 66 + frontend/components/ui/card.tsx | 79 + frontend/components/ui/carousel.tsx | 262 + frontend/components/ui/chart.tsx | 365 ++ frontend/components/ui/checkbox.tsx | 28 + frontend/components/ui/collapsible.tsx | 11 + frontend/components/ui/command.tsx | 153 + frontend/components/ui/context-menu.tsx | 200 + frontend/components/ui/dialog.tsx | 122 + frontend/components/ui/drawer.tsx | 118 + frontend/components/ui/dropdown-menu.tsx | 200 + frontend/components/ui/form.tsx | 178 + frontend/components/ui/hover-card.tsx | 29 + frontend/components/ui/input-otp.tsx | 71 + frontend/components/ui/input.tsx | 22 + frontend/components/ui/label.tsx | 26 + frontend/components/ui/menubar.tsx | 236 + frontend/components/ui/navigation-menu.tsx | 128 + frontend/components/ui/pagination.tsx | 117 + frontend/components/ui/popover.tsx | 31 + frontend/components/ui/progress.tsx | 28 + frontend/components/ui/radio-group.tsx | 44 + frontend/components/ui/resizable.tsx | 45 + frontend/components/ui/scroll-area.tsx | 40 + frontend/components/ui/select.tsx | 160 + frontend/components/ui/separator.tsx | 31 + frontend/components/ui/sheet.tsx | 140 + frontend/components/ui/sidebar.tsx | 763 +++ frontend/components/ui/skeleton.tsx | 15 + frontend/components/ui/slider.tsx | 28 + frontend/components/ui/sonner.tsx | 31 + frontend/components/ui/switch.tsx | 29 + frontend/components/ui/table.tsx | 117 + frontend/components/ui/tabs.tsx | 55 + frontend/components/ui/textarea.tsx | 21 + frontend/components/ui/toast.tsx | 111 + frontend/components/ui/toaster.tsx | 35 + frontend/components/ui/toggle-group.tsx | 61 + frontend/components/ui/toggle.tsx | 45 + frontend/components/ui/tooltip.tsx | 30 + frontend/components/ui/use-mobile.tsx | 19 + frontend/components/ui/use-toast.ts | 179 + frontend/contexts/DnDContext.tsx | 68 + frontend/contexts/NodeDataContext.tsx | 118 + frontend/contexts/SourceClickContext.tsx | 65 + frontend/docker-compose.yml | 15 + frontend/docker-entrypoint.sh | 20 + frontend/docker_build.sh | 2 + frontend/hooks/use-agent-webSocket.ts | 165 + frontend/hooks/use-mobile.tsx | 47 + frontend/hooks/use-toast.ts | 223 + frontend/middleware.ts | 84 + frontend/next.config.mjs | 14 + frontend/package.json | 107 + frontend/pnpm-lock.yaml | 5765 +++++++++++++++++ frontend/postcss.config.mjs | 8 + frontend/public/favicon.svg | 4 + frontend/public/images/discord.webp | Bin 0 -> 21764 bytes frontend/public/images/email.webp | Bin 0 -> 9976 bytes frontend/public/images/evolution-ai-logo.png | Bin 0 -> 1513 bytes frontend/public/images/evolution.png | Bin 0 -> 3273 bytes frontend/public/images/facebook.png | Bin 0 -> 54771 bytes frontend/public/images/imessage.webp | Bin 0 -> 17574 bytes frontend/public/images/instagram.png | Bin 0 -> 1004190 bytes frontend/public/images/linkedin.webp | Bin 0 -> 22324 bytes frontend/public/images/mercadolivre.png | Bin 0 -> 7412 bytes frontend/public/images/sms.png | Bin 0 -> 14570 bytes frontend/public/images/svg/facebook.svg | 1 + frontend/public/images/svg/instagram.svg | 1 + frontend/public/images/svg/whatsapp.svg | 1 + frontend/public/images/telegram.webp | Bin 0 -> 26178 bytes frontend/public/images/threads.png | Bin 0 -> 23302 bytes frontend/public/images/tiktok.webp | Bin 0 -> 31110 bytes frontend/public/images/webchat.webp | Bin 0 -> 27504 bytes frontend/public/images/wechat.png | Bin 0 -> 125907 bytes frontend/public/images/whatsapp.png | Bin 0 -> 53944 bytes frontend/public/images/x-twitter.png | Bin 0 -> 6769 bytes frontend/public/images/youtube.webp | Bin 0 -> 1898 bytes frontend/public/placeholder-logo.png | Bin 0 -> 958 bytes frontend/public/placeholder-logo.svg | 1 + frontend/public/placeholder-user.jpg | Bin 0 -> 2615 bytes frontend/public/placeholder.jpg | Bin 0 -> 1596 bytes frontend/public/placeholder.svg | 1 + frontend/services/agentService.ts | 238 + frontend/services/api.ts | 122 + frontend/services/authService.ts | 56 + frontend/services/clientService.ts | 87 + frontend/services/mcpServerService.ts | 45 + frontend/services/sessionService.ts | 142 + frontend/styles/globals.css | 122 + frontend/tailwind.config.ts | 81 + frontend/tsconfig.json | 27 + frontend/types/agent.ts | 153 + frontend/types/aiModels.ts | 414 ++ frontend/types/auth.ts | 77 + frontend/types/mcpServer.ts | 60 + pyproject.toml | 1 + src/api/a2a_routes.py | 785 ++- src/schemas/a2a_enhanced_types.py | 612 ++ src/services/a2a_sdk_adapter.py | 397 ++ src/services/a2a_task_manager.py | 1069 --- src/services/adk/agent_builder.py | 2 +- src/services/adk/custom_agents/a2a_agent.py | 602 +- src/utils/a2a_enhanced_client.py | 746 +++ 218 files changed, 44036 insertions(+), 1464 deletions(-) create mode 100644 frontend/.cursorrules create mode 100644 frontend/.env.example create mode 100644 frontend/.github/workflows/docker-image.yml create mode 100644 frontend/.github/workflows/publish_docker_image_homolog.yml create mode 100644 frontend/.github/workflows/publish_docker_image_latest.yml create mode 100644 frontend/.gitignore create mode 100644 frontend/CHANGELOG.md create mode 100644 frontend/Dockerfile create mode 100644 frontend/LICENSE create mode 100644 frontend/README.md create mode 100644 frontend/app/agents/AgentCard.tsx create mode 100644 frontend/app/agents/AgentList.tsx create mode 100644 frontend/app/agents/AgentSidebar.tsx create mode 100644 frontend/app/agents/AgentTypeSelector.tsx create mode 100644 frontend/app/agents/EmptyState.tsx create mode 100644 frontend/app/agents/SearchInput.tsx create mode 100644 frontend/app/agents/config/A2AAgentConfig.tsx create mode 100644 frontend/app/agents/config/LLMAgentConfig.tsx create mode 100644 frontend/app/agents/config/LoopAgentConfig copy.tsx create mode 100644 frontend/app/agents/config/ParallelAgentConfig.tsx create mode 100644 frontend/app/agents/config/SequentialAgentConfig.tsx create mode 100644 frontend/app/agents/config/TaskAgentConfig.tsx create mode 100644 frontend/app/agents/dialogs/AgentToolDialog.tsx create mode 100644 frontend/app/agents/dialogs/ApiKeysDialog.tsx create mode 100644 frontend/app/agents/dialogs/ConfirmationDialog.tsx create mode 100644 frontend/app/agents/dialogs/CustomMCPDialog.tsx create mode 100644 frontend/app/agents/dialogs/CustomToolDialog.tsx create mode 100644 frontend/app/agents/dialogs/FolderDialog.tsx create mode 100644 frontend/app/agents/dialogs/ImportAgentDialog.tsx create mode 100644 frontend/app/agents/dialogs/MCPDialog.tsx create mode 100644 frontend/app/agents/dialogs/MoveAgentDialog.tsx create mode 100644 frontend/app/agents/dialogs/ShareAgentDialog.tsx create mode 100644 frontend/app/agents/forms/AgentForm.tsx create mode 100644 frontend/app/agents/forms/BasicInfoTab.tsx create mode 100644 frontend/app/agents/forms/ConfigurationTab.tsx create mode 100644 frontend/app/agents/forms/SubAgentsTab.tsx create mode 100644 frontend/app/agents/page.tsx create mode 100644 frontend/app/agents/workflows/Canva.tsx create mode 100644 frontend/app/agents/workflows/ContextMenu.tsx create mode 100644 frontend/app/agents/workflows/HelperLines.tsx create mode 100644 frontend/app/agents/workflows/NodePanel.tsx create mode 100644 frontend/app/agents/workflows/canva.css create mode 100644 frontend/app/agents/workflows/edges/DefaultEdge.tsx create mode 100644 frontend/app/agents/workflows/edges/index.ts create mode 100644 frontend/app/agents/workflows/nodes/BaseNode.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/agent/AgentChatMessageList.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/agent/AgentForm.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/agent/AgentNode.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/agent/AgentTestChatModal.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/agent/styles.css create mode 100644 frontend/app/agents/workflows/nodes/components/condition/ConditionDialog.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/condition/ConditionForm.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/condition/ConditionNode.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/delay/DelayForm.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/delay/DelayNode.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/message/MessageForm.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/message/MessageNode.tsx create mode 100644 frontend/app/agents/workflows/nodes/components/start/StartNode.tsx create mode 100644 frontend/app/agents/workflows/nodes/index.ts create mode 100644 frontend/app/agents/workflows/nodes/nodeFunctions.ts create mode 100644 frontend/app/agents/workflows/nodes/style.css create mode 100644 frontend/app/agents/workflows/page.tsx create mode 100644 frontend/app/agents/workflows/utils.ts create mode 100644 frontend/app/chat/components/AgentInfoDialog.tsx create mode 100644 frontend/app/chat/components/AttachedFiles.tsx create mode 100644 frontend/app/chat/components/ChatContainer.tsx create mode 100644 frontend/app/chat/components/ChatInput.tsx create mode 100644 frontend/app/chat/components/ChatMessage.tsx create mode 100644 frontend/app/chat/components/FileUpload.tsx create mode 100644 frontend/app/chat/components/InlineDataAttachments.tsx create mode 100644 frontend/app/chat/components/SessionList.tsx create mode 100644 frontend/app/chat/page.tsx create mode 100644 frontend/app/client-layout.tsx create mode 100644 frontend/app/clients/loading.tsx create mode 100644 frontend/app/clients/page.tsx create mode 100644 frontend/app/documentation/components/A2AComplianceCard.tsx create mode 100644 frontend/app/documentation/components/CodeBlock.tsx create mode 100644 frontend/app/documentation/components/CodeExamplesSection.tsx create mode 100644 frontend/app/documentation/components/DocumentationSection.tsx create mode 100644 frontend/app/documentation/components/FrontendImplementationSection.tsx create mode 100644 frontend/app/documentation/components/HttpLabForm.tsx create mode 100644 frontend/app/documentation/components/LabSection.tsx create mode 100644 frontend/app/documentation/components/QuickStartTemplates.tsx create mode 100644 frontend/app/documentation/components/StreamLabForm.tsx create mode 100644 frontend/app/documentation/components/TechnicalDetailsSection.tsx create mode 100644 frontend/app/documentation/page.tsx create mode 100644 frontend/app/globals.css create mode 100644 frontend/app/layout.tsx create mode 100644 frontend/app/login/page.tsx create mode 100644 frontend/app/logout/page.tsx create mode 100644 frontend/app/mcp-servers/loading.tsx create mode 100644 frontend/app/mcp-servers/page.tsx create mode 100644 frontend/app/page.tsx create mode 100644 frontend/app/profile/page.tsx create mode 100644 frontend/app/security/page.tsx create mode 100644 frontend/app/security/reset-password/page.tsx create mode 100644 frontend/app/security/verify-email/page.tsx create mode 100644 frontend/app/shared-chat/AgentInfo.tsx create mode 100644 frontend/app/shared-chat/components/SharedChatPanel.tsx create mode 100644 frontend/app/shared-chat/components/SharedSessionList.tsx create mode 100644 frontend/app/shared-chat/page.tsx create mode 100644 frontend/components.json create mode 100644 frontend/components/ImpersonationBar.tsx create mode 100644 frontend/components/sidebar.tsx create mode 100644 frontend/components/theme-provider.tsx create mode 100644 frontend/components/toaster.tsx create mode 100644 frontend/components/ui/accordion.tsx create mode 100644 frontend/components/ui/alert-dialog.tsx create mode 100644 frontend/components/ui/alert.tsx create mode 100644 frontend/components/ui/aspect-ratio.tsx create mode 100644 frontend/components/ui/avatar.tsx create mode 100644 frontend/components/ui/badge.tsx create mode 100644 frontend/components/ui/breadcrumb.tsx create mode 100644 frontend/components/ui/button.tsx create mode 100644 frontend/components/ui/calendar.tsx create mode 100644 frontend/components/ui/card.tsx create mode 100644 frontend/components/ui/carousel.tsx create mode 100644 frontend/components/ui/chart.tsx create mode 100644 frontend/components/ui/checkbox.tsx create mode 100644 frontend/components/ui/collapsible.tsx create mode 100644 frontend/components/ui/command.tsx create mode 100644 frontend/components/ui/context-menu.tsx create mode 100644 frontend/components/ui/dialog.tsx create mode 100644 frontend/components/ui/drawer.tsx create mode 100644 frontend/components/ui/dropdown-menu.tsx create mode 100644 frontend/components/ui/form.tsx create mode 100644 frontend/components/ui/hover-card.tsx create mode 100644 frontend/components/ui/input-otp.tsx create mode 100644 frontend/components/ui/input.tsx create mode 100644 frontend/components/ui/label.tsx create mode 100644 frontend/components/ui/menubar.tsx create mode 100644 frontend/components/ui/navigation-menu.tsx create mode 100644 frontend/components/ui/pagination.tsx create mode 100644 frontend/components/ui/popover.tsx create mode 100644 frontend/components/ui/progress.tsx create mode 100644 frontend/components/ui/radio-group.tsx create mode 100644 frontend/components/ui/resizable.tsx create mode 100644 frontend/components/ui/scroll-area.tsx create mode 100644 frontend/components/ui/select.tsx create mode 100644 frontend/components/ui/separator.tsx create mode 100644 frontend/components/ui/sheet.tsx create mode 100644 frontend/components/ui/sidebar.tsx create mode 100644 frontend/components/ui/skeleton.tsx create mode 100644 frontend/components/ui/slider.tsx create mode 100644 frontend/components/ui/sonner.tsx create mode 100644 frontend/components/ui/switch.tsx create mode 100644 frontend/components/ui/table.tsx create mode 100644 frontend/components/ui/tabs.tsx create mode 100644 frontend/components/ui/textarea.tsx create mode 100644 frontend/components/ui/toast.tsx create mode 100644 frontend/components/ui/toaster.tsx create mode 100644 frontend/components/ui/toggle-group.tsx create mode 100644 frontend/components/ui/toggle.tsx create mode 100644 frontend/components/ui/tooltip.tsx create mode 100644 frontend/components/ui/use-mobile.tsx create mode 100644 frontend/components/ui/use-toast.ts create mode 100644 frontend/contexts/DnDContext.tsx create mode 100644 frontend/contexts/NodeDataContext.tsx create mode 100644 frontend/contexts/SourceClickContext.tsx create mode 100644 frontend/docker-compose.yml create mode 100755 frontend/docker-entrypoint.sh create mode 100755 frontend/docker_build.sh create mode 100644 frontend/hooks/use-agent-webSocket.ts create mode 100644 frontend/hooks/use-mobile.tsx create mode 100644 frontend/hooks/use-toast.ts create mode 100644 frontend/middleware.ts create mode 100644 frontend/next.config.mjs create mode 100644 frontend/package.json create mode 100644 frontend/pnpm-lock.yaml create mode 100644 frontend/postcss.config.mjs create mode 100644 frontend/public/favicon.svg create mode 100644 frontend/public/images/discord.webp create mode 100644 frontend/public/images/email.webp create mode 100644 frontend/public/images/evolution-ai-logo.png create mode 100644 frontend/public/images/evolution.png create mode 100644 frontend/public/images/facebook.png create mode 100644 frontend/public/images/imessage.webp create mode 100644 frontend/public/images/instagram.png create mode 100644 frontend/public/images/linkedin.webp create mode 100644 frontend/public/images/mercadolivre.png create mode 100644 frontend/public/images/sms.png create mode 100644 frontend/public/images/svg/facebook.svg create mode 100644 frontend/public/images/svg/instagram.svg create mode 100644 frontend/public/images/svg/whatsapp.svg create mode 100644 frontend/public/images/telegram.webp create mode 100644 frontend/public/images/threads.png create mode 100644 frontend/public/images/tiktok.webp create mode 100644 frontend/public/images/webchat.webp create mode 100644 frontend/public/images/wechat.png create mode 100644 frontend/public/images/whatsapp.png create mode 100644 frontend/public/images/x-twitter.png create mode 100644 frontend/public/images/youtube.webp create mode 100644 frontend/public/placeholder-logo.png create mode 100644 frontend/public/placeholder-logo.svg create mode 100644 frontend/public/placeholder-user.jpg create mode 100644 frontend/public/placeholder.jpg create mode 100644 frontend/public/placeholder.svg create mode 100644 frontend/services/agentService.ts create mode 100644 frontend/services/api.ts create mode 100644 frontend/services/authService.ts create mode 100644 frontend/services/clientService.ts create mode 100644 frontend/services/mcpServerService.ts create mode 100644 frontend/services/sessionService.ts create mode 100644 frontend/styles/globals.css create mode 100644 frontend/tailwind.config.ts create mode 100644 frontend/tsconfig.json create mode 100644 frontend/types/agent.ts create mode 100644 frontend/types/aiModels.ts create mode 100644 frontend/types/auth.ts create mode 100644 frontend/types/mcpServer.ts create mode 100644 src/schemas/a2a_enhanced_types.py create mode 100644 src/services/a2a_sdk_adapter.py delete mode 100644 src/services/a2a_task_manager.py create mode 100644 src/utils/a2a_enhanced_client.py diff --git a/frontend/.cursorrules b/frontend/.cursorrules new file mode 100644 index 00000000..5d384dd9 --- /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/.env.example b/frontend/.env.example new file mode 100644 index 00000000..f9feddb3 --- /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/.github/workflows/docker-image.yml b/frontend/.github/workflows/docker-image.yml new file mode 100644 index 00000000..32994151 --- /dev/null +++ b/frontend/.github/workflows/docker-image.yml @@ -0,0 +1,48 @@ +name: Build Docker image + +on: + push: + tags: + - "*.*.*" + +jobs: + build_deploy: + name: Build and Deploy + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: evoapicloud/evo-ai-frontend + tags: type=semver,pattern=v{{version}} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v5 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} \ No newline at end of file diff --git a/frontend/.github/workflows/publish_docker_image_homolog.yml b/frontend/.github/workflows/publish_docker_image_homolog.yml new file mode 100644 index 00000000..b292329b --- /dev/null +++ b/frontend/.github/workflows/publish_docker_image_homolog.yml @@ -0,0 +1,48 @@ +name: Build Docker image + +on: + push: + branches: + - develop + +jobs: + build_deploy: + name: Build and Deploy + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: evoapicloud/evo-ai-frontend + tags: homolog + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v5 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} \ No newline at end of file diff --git a/frontend/.github/workflows/publish_docker_image_latest.yml b/frontend/.github/workflows/publish_docker_image_latest.yml new file mode 100644 index 00000000..deeb2aab --- /dev/null +++ b/frontend/.github/workflows/publish_docker_image_latest.yml @@ -0,0 +1,48 @@ +name: Build Docker image + +on: + push: + branches: + - main + +jobs: + build_deploy: + name: Build and Deploy + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: evoapicloud/evo-ai-frontend + tags: latest + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v5 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 00000000..400e48ed --- /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 00000000..7a1f9205 --- /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 00000000..1560e70b --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,63 @@ +# 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-evoai.evoapicloud.com + +# Instalar pnpm globalmente +RUN npm install -g pnpm + +# Install dependencies first (caching) +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +# Instalar explicitamente o next-runtime-env +RUN pnpm add next-runtime-env + +# Copy source code +COPY . . + +# Set environment variables from build arguments +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} + +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 + +# Instalar pnpm globalmente +RUN npm install -g pnpm + +# Install production dependencies only +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --prod --frozen-lockfile + +# Instalar explicitamente o next-runtime-env na produção +RUN pnpm add next-runtime-env + +# 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 - create it diretamente no container +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 00000000..727e6b0a --- /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 00000000..baf04986 --- /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 00000000..8a504d5c --- /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(); + }; + + // Função para exportar o agente como 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); + } + }; + + // Função para testar o agente A2A no laboratório + const handleTestA2A = () => { + // Usar a URL do agent card como URL base para testes A2A + const agentUrl = agent.agent_card_url?.replace( + "/.well-known/agent.json", + "" + ); + + // Usar a API key diretamente do config do agente + const apiKey = agent.config?.api_key; + + // Construir a URL com parâmetros para o laboratório de testes + const params = new URLSearchParams(); + + if (agentUrl) { + params.set("agent_url", agentUrl); + } + + if (apiKey) { + params.set("api_key", apiKey); + } + + // Redirecionar para o laboratório de testes na aba "lab" + 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 00000000..6eb55af8 --- /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 00000000..16358107 --- /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 00000000..35db3def --- /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 00000000..b084c017 --- /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 00000000..f8e30739 --- /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 00000000..99f6a5dd --- /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 00000000..9c3d1449 --- /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} + + ))} +
+ + +
+ +
+ +
+
+