<%* // Extrai informações do nome do arquivo const fileName = tp.file.title;
// Seleção do tipo de nó LOGO NO INÍCIO const nodeType = await tp.system.suggester( [“Flow Index”, “Flow Variables”, “User Variables”, “Code”, “AI”, “API”, “Jump”, “Condition”, “Split”, “HubSpot”, “HTTP Request”, “Database”, “Mongo”, “Transform”, “Start Inactivity”, “Label”, “Chat”, “Webhook”, “Respond to Webhook”, “RabbitMQ”, “End Inactivity”, “End Flow”, “Finish attendance”, “Iniciar/Atualizar Atendimento”, “Execution Data”, “Wait”], [“Flow Index”, “Flow Variables”, “User Variables”, “Code”, “AI”, “API”, “Jump”, “Condition”, “Split”, “HubSpot”, “HTTP Request”, “Database”, “Mongo”, “Transform”, “Start Inactivity”, “Label”, “Chat”, “Webhook”, “Respond to Webhook”, “RabbitMQ”, “End Inactivity”, “End Flow”, “Finish attendance”, “Iniciar/Atualizar Atendimento”, “Execution Data”, “Wait”], false, “Selecione o tipo do nó” );
// --- Lógica Condicional por Tipo de Nó --- let inputsContent = ""; let outputsContent = ""; let relationsContent = `## Relações
← Recebe de: → Envia para: `;
if (nodeType === “Condition”) { let conditions = []; let addMore = true;
while (addMore) { const valorEntrada = await tp.system.prompt(“Valor de entrada (ex: {{flow.is_weekend}})”); const tipoCondicao = await tp.system.prompt(“Tipo de condição (ex: =, !=, >, <, contains)”); const param2 = await tp.system.prompt(“Param 2 (valor a comparar)”); const nomeCondicao = await tp.system.prompt(“Nome da condição”);
conditions.push({ valorEntrada, tipoCondicao, param2, nomeCondicao });
const continuar = await tp.system.suggester(
["Adicionar outra condição", "Finalizar"],
[true, false],
false,
"Deseja adicionar mais condições?"
);
addMore = continuar;
}
inputsContent = ## Configuração da Condição\n\n;
conditions.forEach((cond, index) ⇒ {
inputsContent += ### Condição ${index + 1}\n\n;
inputsContent += | Campo | Valor |\n|-------|-------|\n;
inputsContent += | **Valor de entrada** | \{cond.valorEntrada.replace(/\|/g, '\\|')}\` |\n`;
inputsContent += `| **Tipo de condição** | {cond.tipoCondicao} |\n; inputsContent += | Param 2 | `{cond.param2}\` |\n`;
inputsContent += `| **Nome da condição** | {cond.nomeCondicao} |\n; inputsContent += | Segue para | |\n\n`;
});
inputsContent += ### Senão\n\n;
inputsContent += | Campo | Valor |\n;
inputsContent += |--------------|-------|\n;
inputsContent += | **Segue para** | |\n\n;
outputsContent = `## Saídas
- Baseado no resultado da condição, o fluxo segue para o próximo nó apropriado`;
} else if (nodeType === “Split”) { let branches = []; let addMore = true;
while (addMore) { const porcentagem = await tp.system.prompt(“Porcentagem (ex: 50%)”); const nomeRamificacao = await tp.system.prompt(“Nome da ramificação”);
branches.push({ porcentagem, nomeRamificacao });
const continuar = await tp.system.suggester(
["Adicionar outra ramificação", "Finalizar"],
[true, false],
false,
"Deseja adicionar mais ramificações?"
);
addMore = continuar;
}
inputsContent = ## Configuração do Split\n\n;
inputsContent += | Porcentagem | Ramificação | Segue para |\n;
inputsContent += |-------------|-------------|------------|\n;
branches.forEach((branch) ⇒ {
inputsContent += | ${branch.porcentagem} | ${branch.nomeRamificacao} | |\n;
});
outputsContent = `## Saídas
- A execução é dividida entre as ramificações configuradas`;
} else if (nodeType === “Label”) { const rotulo = await tp.system.prompt(“Rótulo (ex: ‘Low Touch - Interessado’)”);
inputsContent = `## Rótulo
Rótulo: ${rotulo}`;
outputsContent = `## Saídas
N/A (Este nó apenas aplica um rótulo)`;
} else if (nodeType === “Flow Variables”) { const jsonBlock = await tp.system.prompt(“Cole o bloco JSON completo das variáveis”);
// Formata o JSON com indentação adequada let formattedJson = jsonBlock; try { const parsed = JSON.parse(jsonBlock); formattedJson = JSON.stringify(parsed, null, 2); } catch (e) { // Se não conseguir parsear, usa o texto original formattedJson = jsonBlock; }
inputsContent = `## Variáveis do Fluxo
```json ${formattedJson} ````;
// Tenta parsear para gerar saídas try { const parsed = JSON.parse(jsonBlock); outputsContent = `## Saídas
; Object.keys(parsed).forEach(key => { outputsContent += - `flow.{parsed[key]}\n; }); } catch (e) { outputsContent = Saídas
- Variáveis definidas conforme JSON acima`; }
} else if (nodeType === “User Variables”) { const jsonBlock = await tp.system.prompt(“Cole o bloco JSON completo das variáveis de usuário”);
// Formata o JSON com indentação adequada let formattedJson = jsonBlock; try { const parsed = JSON.parse(jsonBlock); formattedJson = JSON.stringify(parsed, null, 2); } catch (e) { // Se não conseguir parsear, usa o texto original formattedJson = jsonBlock; }
inputsContent = `## Variáveis de Usuário
```json ${formattedJson} ````;
// Tenta parsear para gerar saídas try { const parsed = JSON.parse(jsonBlock); outputsContent = `## Saídas
; Object.keys(parsed).forEach(key => { outputsContent += - `user.{parsed[key]}\n; }); } catch (e) { outputsContent = Saídas
- Variáveis definidas conforme JSON acima`; }
} else if (nodeType === “Code”) { const codeBlock = await tp.system.prompt(“Cole o bloco de código JavaScript”);
relationsContent = `## Relações
← Recebe de: → Envia para (Sucesso): → Envia para (Erro): `;
inputsContent = `## Código
```javascript ${codeBlock} ````;
outputsContent = `## Saídas
- Resultado da execução do código acima`;
} else if (nodeType === “Jump”) { const fluxoDestino = await tp.system.prompt(“Fluxo de destino”); const dataJson = await tp.system.prompt(“Data (Cole o JSON com dados a serem passados)”); const retorno = await tp.system.prompt(“Retorno (true ou false)”);
// Formata o JSON do data let formattedData = dataJson; try { const parsed = JSON.parse(dataJson); formattedData = JSON.stringify(parsed, null, 2); } catch (e) { formattedData = dataJson; }
inputsContent = `## Configuração do Jump
Fluxo de destino: ${fluxoDestino}
Data: ```json ${formattedData} ```
Retorno: ${retorno}`;
} else if (nodeType === “Chat”) { const conteudo = await tp.system.prompt(“Conteúdo da mensagem”); const rodape = await tp.system.prompt(“Rodapé (deixe vazio se não houver)”, ""); const botoes = await tp.system.prompt(“Botões (ex: Acessar app Konsi (https://konsi.com.br))”, ""); const aguardarResposta = await tp.system.suggester([“Sim”, “Não”], [true, false], false, “Aguardar resposta do usuário?”); const tratarForaContexto = await tp.system.suggester([“Sim”, “Não”], [true, false], false, “Tratar mensagem fora de contexto?”); const continuarAuto = await tp.system.suggester([“Sim”, “Não”], [true, false], false, “Continuar automaticamente?”);
inputsContent = `## Configuração do Chat
Conteúdo: ${conteudo}
Rodapé: ${rodape || “N/A”}
Botões: ${botoes || “N/A”}
Opções:
-
Aguardar resposta do usuário: ${aguardarResposta}
-
Tratar mensagem fora de contexto: ${tratarForaContexto}
-
Continuar automaticamente: ${continuarAuto}`;
outputsContent = `## Saídas
N/A (Interação com usuário via chat)`;
} else if (nodeType === “HTTP Request”) { const url = await tp.system.prompt(“URL”);
relationsContent = `## Relações
← Recebe de: → Envia para (Sucesso): → Envia para (Erro): `; const metodo = await tp.system.prompt(“Método (GET, POST, PUT, DELETE, etc)”); const headers = await tp.system.prompt(“Headers (Cole o JSON ou deixe vazio)”, ""); const body = await tp.system.prompt(“Body (Cole o JSON ou deixe vazio)”, "");
// Formata headers se fornecido
let headersContent = “N/A”;
if (headers) {
try {
const parsed = JSON.parse(headers);
headersContent = \n\“json\n${JSON.stringify(parsed, null, 2)}\n````;
} catch (e) {
headersContent = headers;
}
}
// Formata body se fornecido
let bodyContent = “N/A”;
if (body) {
try {
const parsed = JSON.parse(body);
bodyContent = \n\“json\n${JSON.stringify(parsed, null, 2)}\n````;
} catch (e) {
bodyContent = body;
}
}
inputsContent = `## Configuração da Requisição
URL: ${url}
Método: ${metodo}
Headers: ${headersContent}
Body: ${bodyContent}`;
outputsContent = `## Saídas
- Resposta da requisição HTTP (depende do retorno da API)`;
} else if (nodeType === “Start Inactivity”) { const tempo = await tp.system.prompt(“Tempo de inatividade (minutos)”);
inputsContent = `## Configuração de Inatividade
Tempo de inatividade: ${tempo} minutos`;
outputsContent = `## Saídas
- Avança para o próximo nó após o período de inatividade configurado`;
} else if (nodeType === “HubSpot”) { const entidade = await tp.system.prompt(“Entidade (ex: contacts, deals, companies)”); const operacao = await tp.system.prompt(“Operação (ex: create, update, search)”); const campos = await tp.system.prompt(“Campos (Cole o JSON de campos ou deixe vazio)”, ""); const id = await tp.system.prompt(“ID (Preencher apenas para operações de update/search por ID)”, "");
// Formata Campos se fornecido
let camposContent = “N/A”;
if (campos) {
try {
const parsed = JSON.parse(campos);
camposContent = \n\“json\n${JSON.stringify(parsed, null, 2)}\n````;
} catch (e) {
camposContent = campos; // Se não for JSON válido, usa o texto original
}
}
inputsContent = `## Configuração do HubSpot
Entidade: ${entidade}
Operação: ${operacao}
Campos: ${camposContent}
ID: ${id || “N/A”}
Protocolo da conversa HF: Link para o chat `;
outputsContent = `## Saídas
- Resultado da operação no HubSpot (depende da entidade e operação)`;
} else if (nodeType === “End Inactivity”) {
outputsContent = `## Saídas
- Interrompe o monitoramento de inatividade em andamento`;
} else if (nodeType === “RabbitMQ”) { const rabbitMqOpType = await tp.system.suggester( [“Trigger”, “Action”], [“Trigger”, “Action”], false, “Selecione o tipo de operação RabbitMQ” );
if (rabbitMqOpType === “Trigger”) { const queueName = await tp.system.prompt(“Nome da fila”); const acknowledge = await tp.system.suggester([“Automático”, “Manual”], [“Automático”, “Manual”], false, “Reconhecimento (Acknowledge)”); const prefetchCount = await tp.system.prompt(“Prefetch Count (número de mensagens a pré-buscar)”);
inputsContent = `## Configuração do RabbitMQ Trigger
| Campo | Valor |
|---|---|
| Tipo de Operação | Trigger |
| Nome da fila | `${queueName.replace(//g, '\\’)}` |
| Reconhecimento (ack) | ${acknowledge} |
| Prefetch Count | `${prefetchCount.replace(//g, '\\’)}` |
outputsContent = `## Saídas
-
`output.message`: O conteúdo da mensagem consumida (geralmente JSON ou string).
-
`output.properties`: Objeto com as propriedades da mensagem (headers, routingKey, etc.).`;
} else if (rabbitMqOpType === “Action”) { const rabbitMqActionType = await tp.system.suggester( [“Enviar Mensagem”, “Apagar Conteúdo da Fila”], [“Enviar Mensagem”, “Apagar Conteúdo da Fila”], false, “Selecione a ação” );
if (rabbitMqActionType === “Enviar Mensagem”) { const destination = await tp.system.prompt(“Nome da fila/exchange de destino”); const messageBody = await tp.system.prompt(“Corpo da mensagem (conteúdo a ser enviado, Cole JSON ou string)”); const routingKey = await tp.system.prompt(“Routing Key (opcional, para exchanges, deixe vazio se não houver)”, ""); const messageProperties = await tp.system.prompt(“Propriedades da mensagem (opcional, Cole JSON para headers, persistent, etc.)”, "");
let formattedMessageBody = messageBody; try { const parsed = JSON.parse(messageBody); formattedMessageBody = `\`\`\`json\n${JSON.stringify(parsed, null, 2)}\n\`\`\``; } catch (e) { formattedMessageBody = `\`${messageBody.replace(/`/g, '\\`')}\``; // Use monospace for non-JSON strings } let formattedMessageProperties = "N/A"; if (messageProperties) { try { const parsed = JSON.parse(messageProperties); formattedMessageProperties = `\n\`\`\`json\n${JSON.stringify(parsed, null, 2)}\n\`\`\``; } catch (e) { formattedMessageProperties = messageProperties; } } inputsContent = `## Configuração do RabbitMQ Action (Enviar Mensagem)
| Campo | Valor |
|---|---|
| Tipo de Operação | Action |
| Ação | Enviar Mensagem |
| Fila/Exchange de destino | `${destination.replace(//g, '\\’)}` |
| Corpo da mensagem | ${formattedMessageBody} |
| Routing Key | `${routingKey.replace(//g, '\\’) |
| Propriedades da mensagem | ${formattedMessageProperties} |
outputsContent = `## Saídas
-
`output.status`: `success` ou `failure`.
-
`output.details`: Detalhes sobre a operação (ex: ID da mensagem).`;
} else if (rabbitMqActionType === “Apagar Conteúdo da Fila”) { const targetQueue = await tp.system.prompt(“Nome da fila alvo”); const confirmPurge = await tp.system.suggester([“Sim”, “Não”], [true, false], false, “Confirmar Apagar (todos os conteúdos da fila serão removidos)”);
inputsContent = `## Configuração do RabbitMQ Action (Apagar Conteúdo da Fila)
| Campo | Valor |
|---|---|
| Tipo de Operação | Action |
| Ação | Apagar Conteúdo da Fila |
| Fila alvo | `${targetQueue.replace(//g, '\\’)}` |
| Confirmar Apagar | `${confirmPurge}` |
outputsContent = `## Saídas
- `output.status`: `success` ou `failure`.
- `output.messages_purged`: Número de mensagens removidas.`; } }
} else if (nodeType === “End Flow”) { const status = await tp.system.suggester([“Sucesso”, “Erro”], [“Success”, “Error”], false, “Status de finalização”); const retorno = await tp.system.prompt(“Retorno (Cole o JSON ou deixe vazio)”, "");
// Formata o JSON
let formattedRetorno = “N/A”;
if (retorno) {
try {
const parsed = JSON.parse(retorno);
formattedRetorno = \n\“json\n${JSON.stringify(parsed, null, 2)}\n````;
} catch (e) {
formattedRetorno = retorno;
}
}
inputsContent = `## Configuração de Fim de Fluxo
Status: ${status}
Retorno: ${formattedRetorno}`;
relationsContent = `## Relações
← Recebe de: `;
outputsContent = `## Saídas
- Finaliza a execução do fluxo atual`;
} else if (nodeType === “Mongo”) { const resource = await tp.system.prompt(“Resource (ex: mongo-prod)”); const operation = await tp.system.prompt(“Operation (ex: find, insert, update)”); const collection = await tp.system.prompt(“Collection (ex: users, logs)”); const fields = await tp.system.prompt(“Fields (Cole o JSON de campos ou deixe vazio)”, "");
// Formata Fields se fornecido
let fieldsContent = “N/A”;
if (fields) {
try {
const parsed = JSON.parse(fields);
fieldsContent = \n\“json\n${JSON.stringify(parsed, null, 2)}\n````;
} catch (e) {
fieldsContent = fields;
}
}
inputsContent = `## Configuração do Mongo
Resource: ${resource}
Operation: ${operation}
Collection: ${collection}
Fields: ${fieldsContent}`;
outputsContent = `## Saídas
- Resultado da operação no Mongo (depende da operação)`;
} else if (nodeType === “Finish attendance”) { const classificacao = await tp.system.prompt(“Classificação (ex: Atendimento Finalizado, Cliente Inativo)”); const status = await tp.system.prompt(“Status”); const continuarAutomaticamente = await tp.system.suggester( [“Sim”, “Não”], [true, false], false, “Continuar automaticamente para o próximo nó?” );
inputsContent = `## Configuração de Finalizar Atendimento
Classificação: ${classificacao}
Status: ${status}
Continuar automaticamente: ${continuarAutomaticamente ? “Sim” : “Não”}`;
outputsContent = `## Saídas
N/A (Finaliza o atendimento, o fluxo pode continuar ou parar dependendo da configuração)`;
} else if (nodeType === “Execution Data”) { // <<< INÍCIO DO NOVO BLOCO let searchKeys = []; let addMore = true;
while (addMore) { const key = await tp.system.prompt(“Chave de busca (ex: order_id)”); const value = await tp.system.prompt(“Valor da chave (ex: {{flow.order_id}})”);
searchKeys.push({ key, value });
const continuar = await tp.system.suggester(
["Adicionar outro par Key/Value", "Finalizar"],
[true, false],
false,
"Deseja adicionar mais pares de Key/Value?"
);
addMore = continuar;
}
inputsContent = `## Configuração de Dados de Execução
| Chave | Valor |
|-------|-------|\n; searchKeys.forEach(item => { inputsContent += | `{item.key.replace(/`/g, '\\`')}\` | \`{item.value.replace(//g, '\\’)}` |\n`;
});
outputsContent = `## Saídas
N/A (Este nó é usado para indexação e busca de execuções no N8N)`;
} else if (nodeType === “End Flow”) { const status = await tp.system.suggester([“Sucesso”, “Erro”], [“Success”, “Error”], false, “Status de finalização”);
} else if (nodeType === “Webhook”) { const url = await tp.system.prompt(“URL do webhook”); const metodo = await tp.system.prompt(“Método HTTP (GET, POST, PUT, DELETE, etc)”); const authMethod = await tp.system.prompt(“Authentication method (deixe vazio se não houver)”, ""); const respond = await tp.system.prompt(“Respond With (deixe vazio se não houver)”, "");
inputsContent = `## Configuração do Webhook
| Campo | Valor |
|---|---|
| URL | ${url} |
| Método | ${metodo} |
| Authentication method | ${authMethod |
| Respond | ${respond |
outputsContent = `## Saídas
- Dados recebidos via webhook (depende da requisição externa)`;
} else if (nodeType === “Respond to Webhook”) { const respond_with = await tp.system.prompt(“Respond With”); const response_body = await tp.system.prompt(“Response Body”);
inputsContent = `## Configuração do Response to Webhook
| Campo | Valor |
|---|---|
| Respond With | ${respond_with} |
| Response Body | ${response_body} |
outputsContent = `## Saídas
- Dados recebidos via webhook (depende da requisição externa)`;
} else if (nodeType === “Execution Data”) { let searchKeys = []; let addMore = true;
while (addMore) { const key = await tp.system.prompt(“Chave de busca (ex: order_id)”); const value = await tp.system.prompt(“Valor da chave (ex: {{flow.order_id}})”);
searchKeys.push({ key, value });
const continuar = await tp.system.suggester(
["Adicionar outro par Key/Value", "Finalizar"],
[true, false],
false,
"Deseja adicionar mais pares de Key/Value?"
);
addMore = continuar;
}
inputsContent = `## Configuração de Dados de Execução
| Chave | Valor |
|-------|-------|\n; searchKeys.forEach(item => { inputsContent += | `{item.key.replace(/`/g, '\\`')}\` | \`{item.value.replace(//g, '\\’)}` |\n`;
});
outputsContent = `## Saídas
N/A (Este nó é usado para indexação e busca de execuções no N8N)`;
} else if (nodeType === “Wait”) { // <<< INÍCIO DO NOVO BLOCO “Wait” const resumeType = await tp.system.suggester( [“After time interval”, “At specified time”, “On webhook call”, “On form submitted”], [“After time interval”, “At specified time”, “On webhook call”, “On form submitted”], false, “Tipo de Resumo (Resume)” );
let waitAmount = “N/A”; let waitUnit = “N/A”; let optionalDetails = "";
if (resumeType === “After time interval”) { waitAmount = await tp.system.prompt(“Quantidade de espera (Wait amount - ex: 5)”); waitUnit = await tp.system.suggester( [“Seconds”, “Minutes”, “Hours”, “Days”], [“Seconds”, “Minutes”, “Hours”, “Days”], false, “Unidade de espera (Wait unit)” ); } else if (resumeType === “At specified time”) { waitAmount = await tp.system.prompt(“Data e Hora específicas para retomar (ex: {{flow.target_datetime}})”); waitUnit = “Data/Hora Específica”; } else { // “On webhook call” or “On form submitted” optionalDetails = await tp.system.prompt(“Detalhes (URL do Webhook ou Descrição do Formulário, opcional)”, ""); }
inputsContent = `## Configuração do Nó Wait
| Campo | Valor |
|---|---|
| Tipo de Resumo | ${resumeType} |
if (waitAmount !== “N/A”) {
inputsContent += \n| **Quantidade de Espera** | \{waitAmount.replace(/`/g, '\\`')}\` |`;
}
if (waitUnit !== "N/A") {
inputsContent += `\n| **Unidade de Espera** | {waitUnit} |; } if (optionalDetails) { inputsContent += \n| Detalhes | `${optionalDetails.replace(//g, '\\’)}` |`;
}
outputsContent = `## Saídas
-
O fluxo aguarda a condição de resumo ser atendida para prosseguir.
-
Se ‘On webhook call’ ou ‘On form submitted’, a saída é acionada pela chamada externa.
-
Se ‘After time interval’ ou ‘At specified time’, a saída ocorre após o período configurado.`;
relationsContent = `## Relações
← Recebe de: → Envia para (Após Resumo): `;
}else if (nodeType === “Iniciar/Atualizar Atendimento”) { const departamento = await tp.system.prompt(“Departamento”);
inputsContent = `## Configuração de Atendimento
Departamento: ${departamento}`;
relationsContent = `## Relações
← Recebe de: → Envia para (Sucesso): → Envia para (Erro): `;
outputsContent = `## Saídas
- Sucesso: Atendimento iniciado/atualizado
- Erro: Falha ao iniciar/atualizar atendimento`;
} else { // Tipos padrão (Flow Index, AI, API, HubSpot, Database, Transform, etc) let inputs = []; let outputs = []; let addMoreInputs = true; let addMoreOutputs = true;
// Coleta de inputs while (addMoreInputs) { const inputField = await tp.system.prompt(“Nome do campo de entrada”); const inputDesc = await tp.system.prompt(“Descrição/exemplo do valor de entrada”);
inputs.push({ field: inputField, desc: inputDesc });
const continuar = await tp.system.suggester(
["Adicionar outro input", "Finalizar inputs"],
[true, false],
false,
"Deseja adicionar mais inputs?"
);
addMoreInputs = continuar;
}
// Coleta de outputs while (addMoreOutputs) { const outputVar = await tp.system.prompt(“Nome da variável de saída”); const outputDesc = await tp.system.prompt(“Descrição da saída”);
outputs.push({ variable: outputVar, desc: outputDesc });
const continuar = await tp.system.suggester(
["Adicionar outro output", "Finalizar outputs"],
[true, false],
false,
"Deseja adicionar mais outputs?"
);
addMoreOutputs = continuar;
}
// Monta o conteúdo de inputs
inputsContent = ## Entradas\n\n\“json\n{\n; inputs.forEach((input, index) => { inputsContent += “{input.desc}“; if (index < inputs.length - 1) inputsContent += ','; inputsContent += '\n'; }); inputsContent += }\n````;
// Monta o conteúdo de outputs
outputsContent = ## Saídas\n\n;
outputs.forEach(output ⇒ {
outputsContent += - \flow.{output.desc}\n`;
});
}
-%>
id: <% fileName %> flow: type: <% nodeType %> tags: [] related: [] revision_state: <% tp.date.now(“X”) %> tracked: false
<% inputsContent %>
<% outputsContent %>
Descrição adicional
<% relationsContent %>