@wondai/n8n-nodes-nucleo 0.6.2 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -2
- package/dist/nodes/Nucleo/Nucleo.node.js +85 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ parede. Isso mantém o segredo fora do workflow, a lógica num lugar só e o tok
|
|
|
26
26
|
| Pedido | Alterar | `PATCH /api/v1/agent/pedido/:id` | `pedido:escrever` |
|
|
27
27
|
| Pedido | Cancelar | `POST /api/v1/agent/pedido/:id/cancelar` | `pedido:escrever` |
|
|
28
28
|
| Conversa | Preparar | `POST /api/v1/agent/conversa/preparar` | `contexto:ler` |
|
|
29
|
-
| Contexto | Consultar
|
|
29
|
+
| Contexto | Consultar por Escopo | `POST /api/v1/agent/contexto/consultar` | `contexto:ler` |
|
|
30
30
|
| Conversa | Registrar | `POST /api/v1/agent/conversa/fechar` | `conversa:escrever` |
|
|
31
31
|
|
|
32
32
|
**Resolver Produtos** é a operação inteligente: manda várias consultas numa chamada (máx 10),
|
|
@@ -66,6 +66,11 @@ alguma linha não traz `produto_id`/`alias` e `quantidade` positiva. É uma prot
|
|
|
66
66
|
o Núcleo continua sendo a autoridade final das regras, mas o workflow não envia pedido vazio por
|
|
67
67
|
erro de tool schema.
|
|
68
68
|
|
|
69
|
+
A partir da v0.6.4, `Pedido Criar` e `Pedido Alterar` aceitam `Cobranças Comerciais (JSON)`.
|
|
70
|
+
Use para adicionais pagos vindos de `Contexto -> commercial_rules`, por exemplo
|
|
71
|
+
`[{"tipo":"paid_addon","nome":"Confetes","valor":35,"origem":"commercial_rules"}]`.
|
|
72
|
+
Essas linhas entram no valor a cobrar, mas nao viram produto de catalogo nem pagamento.
|
|
73
|
+
|
|
69
74
|
**Disponibilidade na Rede** ("tem na outra loja?") é exposta como **tool** do AI Agent, mas com regra
|
|
70
75
|
estrita no prompt: **usar SÓ quando o cliente pedir explicitamente outra unidade**. Passe o `produto_id`
|
|
71
76
|
já resolvido (ou uma `consulta` curta). A loja que pergunta vem do **vínculo do token** (a IA não
|
|
@@ -75,6 +80,16 @@ telefone/endereço (allowlist) e distância opcional. **Disponibilidade NÃO é
|
|
|
75
80
|
declarou e oferece o contato para o cliente confirmar. Este endpoint **não** entra no contexto fixo do
|
|
76
81
|
gate; é chamado sob demanda. Tenant/unidade vêm do token — nunca do prompt.
|
|
77
82
|
|
|
83
|
+
**Contexto -> Consultar por Escopo** deve ser usado como **AI Tool** dentro do agente, sob demanda.
|
|
84
|
+
Passe `escopos` para buscar apenas o necessario:
|
|
85
|
+
|
|
86
|
+
- `hours` exige `data` (`YYYY-MM-DD`) e devolve horario/status da data, sem despejar semana inteira.
|
|
87
|
+
- `identity`, `delivery`, `payment` e `commercial_rules` devolvem somente o recorte pedido.
|
|
88
|
+
- `menus` e `promotions` continuam opcionais e so entram quando a pergunta pedir cardapio/promocao.
|
|
89
|
+
|
|
90
|
+
Chamadas antigas com apenas `data` seguem funcionando como `escopos=["hours"]`, mas o workflow novo nao
|
|
91
|
+
deve injetar horario/endereco/entrega/pagamento/regras comerciais em todo prompt.
|
|
92
|
+
|
|
78
93
|
## Gate da IA — Preparar como PRIMEIRO passo (ADR-021, Plano 004)
|
|
79
94
|
|
|
80
95
|
**Conversa → Preparar** é o **gate determinístico** da IA. Use-o como **node normal** no primeiro
|
|
@@ -86,7 +101,8 @@ A resposta vem sempre em **HTTP 200** e o node a entrega **intacta** (não vira
|
|
|
86
101
|
- `{ "allowed": false, "state": "disabled", "reason": "tenant_disabled" | "unit_disabled" | "configuration_error" | "unavailable" }`
|
|
87
102
|
→ **PARE o fluxo sem responder** ao cliente (a empresa/unidade desligou a IA; falha de consulta também para).
|
|
88
103
|
- `{ "allowed": true, "state": "enabled", "runtime_version": N, "session_id": "...", "primeiro_contato": true, "contexto": { ... } }`
|
|
89
|
-
→ **siga** para memória/router/LLM. O `contexto`
|
|
104
|
+
→ **siga** para memória/router/LLM. O `contexto` inicial e compacto; detalhes de horario,
|
|
105
|
+
endereco, entrega, pagamento, regras comerciais, cardapio e promocoes devem vir da tool Contexto sob demanda.
|
|
90
106
|
|
|
91
107
|
O Núcleo é a fonte da verdade do liga/desliga; o estado `active` do workflow no n8n **não** é usado
|
|
92
108
|
como controle por padaria. Quem desliga é o dono/gerente em `/configuracoes` (ou o super-admin).
|
|
@@ -303,8 +303,8 @@ class Nucleo {
|
|
|
303
303
|
{
|
|
304
304
|
name: "Consultar Data",
|
|
305
305
|
value: "consultar",
|
|
306
|
-
action: "Consultar contexto
|
|
307
|
-
description: "
|
|
306
|
+
action: "Consultar contexto por escopo",
|
|
307
|
+
description: "Busca somente os escopos necessarios (horario, identidade, entrega, pagamento, regras comerciais, cardapios ou promocoes). Use como AI Tool sob demanda, nao como contexto fixo do prompt.",
|
|
308
308
|
},
|
|
309
309
|
],
|
|
310
310
|
default: "consultar",
|
|
@@ -603,6 +603,14 @@ class Nucleo {
|
|
|
603
603
|
description: "Opcional. Desconto concedido em reais (ex.: 5). Abate do valor a cobrar e do troco. 0/vazio = sem desconto.",
|
|
604
604
|
displayOptions: { show: { resource: ["pedido"], operation: ["criar"] } },
|
|
605
605
|
},
|
|
606
|
+
{
|
|
607
|
+
displayName: "Cobranças Comerciais (JSON)",
|
|
608
|
+
name: "cobrancas",
|
|
609
|
+
type: "json",
|
|
610
|
+
default: "[]",
|
|
611
|
+
description: 'Opcional. Array de cobranças comerciais que entram no valor a cobrar sem virar produto: [{"tipo":"paid_addon","nome":"Confetes","valor":35,"origem":"commercial_rules","operational_config_revision_id":"...","snapshot":{"label":"Confetes - R$35,00"}}]. Use quando vier de Contexto Loja/commercial_rules.',
|
|
612
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["criar"] } },
|
|
613
|
+
},
|
|
606
614
|
{
|
|
607
615
|
displayName: "Loja (unit_id)",
|
|
608
616
|
name: "unitId",
|
|
@@ -754,6 +762,14 @@ class Nucleo {
|
|
|
754
762
|
description: "Redefine o desconto (recalcula o valor a cobrar e o pagamento pendente). Ex.: 5. Vazio = não altera o desconto. Use 0 para zerar.",
|
|
755
763
|
displayOptions: { show: { resource: ["pedido"], operation: ["alterar"] } },
|
|
756
764
|
},
|
|
765
|
+
{
|
|
766
|
+
displayName: "Cobranças Comerciais (JSON)",
|
|
767
|
+
name: "cobrancasNovo",
|
|
768
|
+
type: "json",
|
|
769
|
+
default: "[]",
|
|
770
|
+
description: 'Opcional. Substitui as cobranças comerciais do pedido. Envie [] para limpar. Ex.: [{"tipo":"paid_addon","nome":"Confetes","valor":35,"origem":"commercial_rules"}].',
|
|
771
|
+
displayOptions: { show: { resource: ["pedido"], operation: ["alterar"] } },
|
|
772
|
+
},
|
|
757
773
|
{
|
|
758
774
|
displayName: "Motivo",
|
|
759
775
|
name: "motivo",
|
|
@@ -878,9 +894,52 @@ class Nucleo {
|
|
|
878
894
|
name: "data",
|
|
879
895
|
type: "string",
|
|
880
896
|
default: "",
|
|
881
|
-
required:
|
|
897
|
+
required: false,
|
|
882
898
|
placeholder: "2026-12-25",
|
|
883
|
-
description: "
|
|
899
|
+
description: "Obrigatoria apenas quando o escopo incluir Horarios. Use YYYY-MM-DD (janela ±366 dias).",
|
|
900
|
+
displayOptions: { show: { resource: ["contexto"], operation: ["consultar"] } },
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
displayName: "Escopos",
|
|
904
|
+
name: "contextoEscopos",
|
|
905
|
+
type: "multiOptions",
|
|
906
|
+
default: ["hours"],
|
|
907
|
+
description: "Recortes de contexto que a IA precisa para a pergunta atual.",
|
|
908
|
+
options: [
|
|
909
|
+
{ name: "Identidade/Endereco", value: "identity" },
|
|
910
|
+
{ name: "Operacao", value: "operation" },
|
|
911
|
+
{ name: "Horarios", value: "hours" },
|
|
912
|
+
{ name: "Entrega", value: "delivery" },
|
|
913
|
+
{ name: "Pagamento", value: "payment" },
|
|
914
|
+
{ name: "Regras Comerciais", value: "commercial_rules" },
|
|
915
|
+
{ name: "Cardapios", value: "menus" },
|
|
916
|
+
{ name: "Promocoes", value: "promotions" },
|
|
917
|
+
],
|
|
918
|
+
displayOptions: { show: { resource: ["contexto"], operation: ["consultar"] } },
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
displayName: "Cidade",
|
|
922
|
+
name: "contextoCidade",
|
|
923
|
+
type: "string",
|
|
924
|
+
default: "",
|
|
925
|
+
description: "Opcional para validar se a cidade/bairro esta em area de entrega.",
|
|
926
|
+
displayOptions: { show: { resource: ["contexto"], operation: ["consultar"] } },
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
displayName: "Assuntos",
|
|
930
|
+
name: "contextoAssuntos",
|
|
931
|
+
type: "string",
|
|
932
|
+
default: "",
|
|
933
|
+
placeholder: "frete, pagamento",
|
|
934
|
+
description: "Opcional; texto livre separado por linhas ou virgulas para telemetria/contexto da pergunta.",
|
|
935
|
+
displayOptions: { show: { resource: ["contexto"], operation: ["consultar"] } },
|
|
936
|
+
},
|
|
937
|
+
{
|
|
938
|
+
displayName: "Unidade ID",
|
|
939
|
+
name: "contextoUnitId",
|
|
940
|
+
type: "string",
|
|
941
|
+
default: "",
|
|
942
|
+
description: "Opcional e somente compatibilidade: o servidor valida contra o vinculo do token.",
|
|
884
943
|
displayOptions: { show: { resource: ["contexto"], operation: ["consultar"] } },
|
|
885
944
|
},
|
|
886
945
|
// ----------------------------------------------------------------- telemetria:enviar
|
|
@@ -1251,6 +1310,7 @@ class Nucleo {
|
|
|
1251
1310
|
const trocoPara = Number(this.getNodeParameter("trocoPara", i, 0));
|
|
1252
1311
|
const taxaEntrega = Number(this.getNodeParameter("taxaEntrega", i, 0));
|
|
1253
1312
|
const desconto = Number(this.getNodeParameter("desconto", i, 0));
|
|
1313
|
+
const cobrancas = asArray(this.getNodeParameter("cobrancas", i, "[]"));
|
|
1254
1314
|
const unitId = this.getNodeParameter("unitId", i, "").trim();
|
|
1255
1315
|
idempotencyKey =
|
|
1256
1316
|
this.getNodeParameter("idempotencyKey", i, "").trim() || (0, node_crypto_1.randomUUID)();
|
|
@@ -1277,6 +1337,8 @@ class Nucleo {
|
|
|
1277
1337
|
b.taxa_entrega = taxaEntrega;
|
|
1278
1338
|
if (Number.isFinite(desconto) && desconto > 0)
|
|
1279
1339
|
b.desconto = desconto;
|
|
1340
|
+
if (cobrancas.length)
|
|
1341
|
+
b.cobrancas = cobrancas;
|
|
1280
1342
|
if (unitId)
|
|
1281
1343
|
b.unit_id = unitId;
|
|
1282
1344
|
method = "POST";
|
|
@@ -1299,6 +1361,7 @@ class Nucleo {
|
|
|
1299
1361
|
const trocoParaNovo = Number(this.getNodeParameter("trocoParaNovo", i, 0));
|
|
1300
1362
|
const taxaEntregaNova = this.getNodeParameter("taxaEntregaNova", i, "").trim();
|
|
1301
1363
|
const descontoNovo = this.getNodeParameter("descontoNovo", i, "").trim();
|
|
1364
|
+
const cobrancasNovo = asArray(this.getNodeParameter("cobrancasNovo", i, "[]"));
|
|
1302
1365
|
const b = {};
|
|
1303
1366
|
if (observacoes.trim())
|
|
1304
1367
|
b.observacoes = observacoes.trim();
|
|
@@ -1334,6 +1397,8 @@ class Nucleo {
|
|
|
1334
1397
|
if (descontoNovo !== "" && Number.isFinite(Number(descontoNovo))) {
|
|
1335
1398
|
b.desconto = Number(descontoNovo);
|
|
1336
1399
|
}
|
|
1400
|
+
if (cobrancasNovo.length)
|
|
1401
|
+
b.cobrancas = cobrancasNovo;
|
|
1337
1402
|
// Idempotência (opcional): mesma chave num retry → backend não reaplica a alteração.
|
|
1338
1403
|
idempotencyKey =
|
|
1339
1404
|
this.getNodeParameter("idempotencyKey", i, "").trim() || undefined;
|
|
@@ -1402,9 +1467,24 @@ class Nucleo {
|
|
|
1402
1467
|
}
|
|
1403
1468
|
else if (resource === "contexto" && operation === "consultar") {
|
|
1404
1469
|
const data = this.getNodeParameter("data", i).trim();
|
|
1470
|
+
const escopos = this.getNodeParameter("contextoEscopos", i, ["hours"]);
|
|
1471
|
+
const cidade = this.getNodeParameter("contextoCidade", i, "").trim();
|
|
1472
|
+
const assuntos = parseIds(this.getNodeParameter("contextoAssuntos", i, ""));
|
|
1473
|
+
const unitId = this.getNodeParameter("contextoUnitId", i, "").trim();
|
|
1474
|
+
const b = {};
|
|
1475
|
+
if (data)
|
|
1476
|
+
b.data = data;
|
|
1477
|
+
if (Array.isArray(escopos) && escopos.length > 0)
|
|
1478
|
+
b.escopos = escopos;
|
|
1479
|
+
if (cidade)
|
|
1480
|
+
b.cidade = cidade;
|
|
1481
|
+
if (assuntos.length > 0)
|
|
1482
|
+
b.assuntos = assuntos;
|
|
1483
|
+
if (unitId)
|
|
1484
|
+
b.unit_id = unitId;
|
|
1405
1485
|
method = "POST";
|
|
1406
1486
|
path = "/api/v1/agent/contexto/consultar";
|
|
1407
|
-
bodyObj =
|
|
1487
|
+
bodyObj = b;
|
|
1408
1488
|
}
|
|
1409
1489
|
else if (resource === "telemetria" && operation === "enviar") {
|
|
1410
1490
|
const eventKey = this.getNodeParameter("telEventKey", i).trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wondai/n8n-nodes-nucleo",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Node n8n para o Núcleo Wondai — atendimento de IA multi-vertical (gate liga/desliga, cliente/paciente, catálogo fuzzy, pedidos [padaria], procedimento/agenda/agendamento [odonto], contexto operacional, telemetria) com assinatura HMAC v1. Tenant e vertical vêm do token (a parede, ADR-013/038).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|