feat(makefile): update run command to exclude frontend and log files during reload

This commit is contained in:
Davidson Gomes
2025-05-24 10:27:30 -03:00
parent 956d16a854
commit c4a4e5fd68
30 changed files with 2184 additions and 563 deletions

View File

@@ -1,48 +0,0 @@
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 }}

View File

@@ -1,48 +0,0 @@
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 }}

View File

@@ -1,48 +0,0 @@
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 }}

View File

@@ -215,7 +215,7 @@ export function AgentCard({
return new Date(agent.created_at).toLocaleDateString();
};
// Função para exportar o agente como JSON
// Function to export the agent as JSON
const handleExportAgent = () => {
try {
exportAsJson(
@@ -231,18 +231,18 @@ export function AgentCard({
}
};
// Função para testar o agente A2A no laboratório
// Function to test the A2A agent in the lab
const handleTestA2A = () => {
// Usar a URL do agent card como URL base para testes A2A
// Use the agent card URL as base for A2A tests
const agentUrl = agent.agent_card_url?.replace(
"/.well-known/agent.json",
""
);
// Usar a API key diretamente do config do agente
// Use the API key directly from the agent config
const apiKey = agent.config?.api_key;
// Construir a URL com parâmetros para o laboratório de testes
// Build the URL with parameters for the lab tests
const params = new URLSearchParams();
if (agentUrl) {
@@ -253,7 +253,7 @@ export function AgentCard({
params.set("api_key", apiKey);
}
// Redirecionar para o laboratório de testes na aba "lab"
// Redirect to the lab tests in the "lab" tab
const testUrl = `/documentation?${params.toString()}#lab`;
router.push(testUrl);

View File

@@ -440,15 +440,15 @@ export default function AgentsPage() {
setEditingAgent(null);
};
// Função para exportar todos os agentes como JSON
// Function to export all agents as JSON
const handleExportAllAgents = () => {
try {
// Criar nome do arquivo com data atual
// Create file name with current date
const date = new Date();
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
const filename = `agents-export-${formattedDate}`;
// Usar a função utilitária para exportar
// Use the utility function to export
// Pass agents both as the data and as allAgents parameter to properly resolve references
const result = exportAsJson({ agents: filteredAgents }, filename, true, agents);

View File

@@ -189,12 +189,12 @@ const Canva = forwardRef(({ agent }: { agent: Agent | null }, ref) => {
setActiveExecutionNodeId,
}));
// Effect para limpar o nó ativo após um timeout
// Effect to clear the active node after a timeout
useEffect(() => {
if (activeExecutionNodeId) {
const timer = setTimeout(() => {
setActiveExecutionNodeId(null);
}, 5000); // Aumentar para 5 segundos para dar mais tempo de visualização
}, 5000); // Increase to 5 seconds to give more time to visualize
return () => clearTimeout(timer);
}
@@ -218,13 +218,13 @@ const Canva = forwardRef(({ agent }: { agent: Agent | null }, ref) => {
}
}, [agent, setNodes, setEdges]);
// Atualizar os nós quando o nó ativo muda para adicionar classe visual
// Update nodes when the active node changes to add visual class
useEffect(() => {
if (nodes.length > 0) {
setNodes((nds: any) =>
nds.map((node: any) => {
if (node.id === activeExecutionNodeId) {
// Adiciona uma classe para destacar o nó ativo
// Add a class to highlight the active node
return {
...node,
className: "active-execution-node",
@@ -234,7 +234,7 @@ const Canva = forwardRef(({ agent }: { agent: Agent | null }, ref) => {
},
};
} else {
// Remove a classe de destaque
// Remove the highlight class
const { isExecuting, ...restData } = node.data || {};
return {
...node,

View File

@@ -108,15 +108,15 @@ export function AgentForm({ selectedNode, handleUpdateNode, setEdges, setIsOpen,
const [isTestModalOpen, setIsTestModalOpen] = useState(false);
const [isEditMode, setIsEditMode] = useState(false);
// Acessar a referência do canvas a partir do localStorage
// Access the canvas reference from localStorage
const canvasRef = useRef<any>(null);
useEffect(() => {
// Quando o componente é montado, verifica se há uma referência de canvas no contexto global
// When the component is mounted, check if there is a canvas reference in the global context
if (typeof window !== "undefined") {
const workflowsPage = document.querySelector('[data-workflow-page="true"]');
if (workflowsPage) {
// Se estamos na página de workflows, tentamos acessar a ref do canvas
// If we are on the workflows page, try to access the canvas ref
const canvasElement = workflowsPage.querySelector('[data-canvas-ref="true"]');
if (canvasElement && (canvasElement as any).__reactRef) {
canvasRef.current = (canvasElement as any).__reactRef.current;

View File

@@ -89,8 +89,8 @@ export function AgentTestChatModal({ open, onOpenChange, agent, canvasRef }: Age
const onEvent = useCallback((event: any) => {
setMessages((prev) => [...prev, event]);
// Verificar se a mensagem vem de um nó de workflow e destacar o nó
// somente se o canvasRef estiver disponível (chamado do Test Workflow na página principal)
// Check if the message comes from a workflow node and highlight the node
// only if the canvasRef is available (called from Test Workflow on the main page)
if (event.author && event.author.startsWith('workflow-node:') && canvasRef?.current) {
const nodeId = event.author.split(':')[1];
canvasRef.current.setActiveExecutionNodeId(nodeId);
@@ -139,7 +139,7 @@ export function AgentTestChatModal({ open, onOpenChange, agent, canvasRef }: Age
setExternalId(generateExternalId());
setIsInitializing(true);
// Breve delay para mostrar o status de inicialização
// Short delay to show the initialization status
const timer = setTimeout(() => {
setIsInitializing(false);
}, 1200);

View File

@@ -223,7 +223,7 @@ function MessageForm({
</SelectTrigger>
<SelectContent className="bg-neutral-800 border-neutral-700 text-neutral-200">
<SelectItem value="text">Text</SelectItem>
{/* Outras opções podem ser habilitadas no futuro */}
{/* Other options can be enabled in the future */}
{/* <SelectItem value="image">Image</SelectItem>
<SelectItem value="file">File</SelectItem>
<SelectItem value="video">Video</SelectItem> */}

View File

@@ -185,7 +185,7 @@ function WorkflowsContent() {
open={isTestModalOpen}
onOpenChange={setIsTestModalOpen}
agent={agent}
canvasRef={canvaRef} // Passamos a referência do canvas para permitir a visualização dos nós em execução
canvasRef={canvaRef} // Pass the canvas reference to allow visualization of running nodes
/>
)}

View File

@@ -140,7 +140,7 @@ export function AgentInfoDialog({
}
};
// Função para exportar o agente como JSON
// Function to export the agent as JSON
const handleExportAgent = async () => {
if (!agent) return;

View File

@@ -60,9 +60,9 @@ export function ChatInput({
const fileInputRef = useRef<HTMLInputElement>(null);
const textareaRef = useRef<HTMLTextAreaElement>(null);
// Autofocus no textarea quando o componente for montado
// Autofocus the textarea when the component is mounted
React.useEffect(() => {
// Pequeno timeout para garantir que o foco seja aplicado após a renderização completa
// Small timeout to ensure focus is applied after the complete rendering
if (autoFocus) {
const timer = setTimeout(() => {
if (textareaRef.current && !isLoading) {
@@ -87,7 +87,7 @@ export function ChatInput({
setTimeout(() => {
setResetFileUpload(false);
// Mantém o foco no textarea após enviar a mensagem
// Keep the focus on the textarea after sending the message
if (autoFocus && textareaRef.current) {
textareaRef.current.focus();
}

View File

@@ -49,6 +49,11 @@ interface LabSectionProps {
setTaskId: (id: string) => void;
callId: string;
setCallId: (id: string) => void;
a2aMethod: string;
setA2aMethod: (method: string) => void;
authMethod: string;
setAuthMethod: (method: string) => void;
generateNewIds: () => void;
sendRequest: () => Promise<void>;
sendStreamRequestWithEventSource: () => Promise<void>;
isLoading: boolean;
@@ -76,6 +81,11 @@ export function LabSection({
setTaskId,
callId,
setCallId,
a2aMethod,
setA2aMethod,
authMethod,
setAuthMethod,
generateNewIds,
sendRequest,
sendStreamRequestWithEventSource,
isLoading,
@@ -125,6 +135,11 @@ export function LabSection({
setTaskId={setTaskId}
callId={callId}
setCallId={setCallId}
a2aMethod={a2aMethod}
setA2aMethod={setA2aMethod}
authMethod={authMethod}
setAuthMethod={setAuthMethod}
generateNewIds={generateNewIds}
sendRequest={sendRequest}
isLoading={isLoading}
/>
@@ -144,6 +159,7 @@ export function LabSection({
setTaskId={setTaskId}
callId={callId}
setCallId={setCallId}
authMethod={authMethod}
sendStreamRequest={sendStreamRequestWithEventSource}
isStreaming={isStreaming}
streamResponse={streamResponse}

View File

@@ -851,12 +851,12 @@ function DocumentationContent() {
body: JSON.stringify(streamRpcRequest),
});
// Verificar o content-type da resposta
// Verify the content-type of the response
const contentType = initialResponse.headers.get("Content-Type");
addDebugLog(`Response content type: ${contentType || "not specified"}`);
if (contentType && contentType.includes("text/event-stream")) {
// É uma resposta SSE (Server-Sent Events)
// It's an SSE (Server-Sent Events) response
addDebugLog("Detected SSE response, processing stream directly");
processEventStream(initialResponse);
return;
@@ -877,10 +877,10 @@ function DocumentationContent() {
try {
const responseText = await initialResponse.text();
// Verificar se a resposta começa com "data:", o que indica um SSE
// Verify if the response starts with "data:", which indicates an SSE
if (responseText.trim().startsWith("data:")) {
addDebugLog("Response has SSE format but wrong content-type");
// Criar uma resposta sintética para processar como stream
// Create a synthetic response to process as stream
const syntheticResponse = new Response(responseText, {
headers: {
"Content-Type": "text/event-stream",
@@ -890,7 +890,7 @@ function DocumentationContent() {
return;
}
// Tentar processar como JSON
// Try to process as JSON
const initialData = JSON.parse(responseText);
addDebugLog("Initial stream response: " + JSON.stringify(initialData));
@@ -913,7 +913,7 @@ function DocumentationContent() {
} catch (parseError) {
addDebugLog(`Error parsing response: ${parseError}`);
// Se não conseguimos processar como JSON ou SSE, mostrar o erro
// If we can't process as JSON or SSE, show the error
setStreamResponse(
`Error: Unable to process response: ${parseError instanceof Error ? parseError.message : String(parseError)}`
);

View File

@@ -71,7 +71,6 @@
"cmdk": "1.0.4",
"date-fns": "2.28.0",
"embla-carousel-react": "8.5.1",
"evo-ai-frontend": "file:",
"input-otp": "1.4.1",
"lucide-react": "^0.454.0",
"next": "15.2.4",