@wondai/n8n-nodes-nucleo 0.2.5 → 0.2.6
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/dist/nodes/Nucleo/Nucleo.node.js +51 -32
- package/package.json +1 -1
|
@@ -15,6 +15,7 @@ const n8n_workflow_1 = require("n8n-workflow");
|
|
|
15
15
|
* signature = HMAC_SHA256(signingSecret, canônica) em hex.
|
|
16
16
|
*/
|
|
17
17
|
const SIGNATURE_VERSION = "v1";
|
|
18
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
18
19
|
const HEADERS = {
|
|
19
20
|
key: "x-wondai-key",
|
|
20
21
|
timestamp: "x-wondai-timestamp",
|
|
@@ -599,7 +600,9 @@ class Nucleo {
|
|
|
599
600
|
const b = { resumo, resultado };
|
|
600
601
|
if (convTelefone)
|
|
601
602
|
b.telefone = convTelefone;
|
|
602
|
-
|
|
603
|
+
// pedido_id é opcional e a IA costuma alucinar ("nenhum", texto, UUID stale).
|
|
604
|
+
// Só envia se for UUID bem-formado — lixo nunca chega ao Núcleo.
|
|
605
|
+
if (convPedidoId && UUID_RE.test(convPedidoId))
|
|
603
606
|
b.pedido_id = convPedidoId;
|
|
604
607
|
idempotencyKey =
|
|
605
608
|
this.getNodeParameter("convIdempotencyKey", i, "").trim() || undefined;
|
|
@@ -613,38 +616,54 @@ class Nucleo {
|
|
|
613
616
|
});
|
|
614
617
|
}
|
|
615
618
|
// ---- assina e envia (HMAC v1) ----
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
619
|
+
const sendSigned = async (rawBody) => {
|
|
620
|
+
const timestamp = Math.floor(Date.now() / 1000).toString();
|
|
621
|
+
const nonce = (0, node_crypto_1.randomUUID)();
|
|
622
|
+
const canonical = canonicalString(method, path, timestamp, nonce, rawBody);
|
|
623
|
+
const signature = sign(signingSecret, canonical);
|
|
624
|
+
const headers = {
|
|
625
|
+
[HEADERS.key]: tokenId,
|
|
626
|
+
[HEADERS.timestamp]: timestamp,
|
|
627
|
+
[HEADERS.nonce]: nonce,
|
|
628
|
+
[HEADERS.signature]: signature,
|
|
629
|
+
};
|
|
630
|
+
if (rawBody)
|
|
631
|
+
headers["content-type"] = "application/json";
|
|
632
|
+
if (idempotencyKey)
|
|
633
|
+
headers["idempotency-key"] = idempotencyKey;
|
|
634
|
+
const res = await this.helpers.httpRequest({
|
|
635
|
+
method,
|
|
636
|
+
url: baseUrl + path,
|
|
637
|
+
headers,
|
|
638
|
+
body: rawBody || undefined,
|
|
639
|
+
json: false,
|
|
640
|
+
returnFullResponse: true,
|
|
641
|
+
ignoreHttpStatusErrors: true,
|
|
642
|
+
});
|
|
643
|
+
const status = res.statusCode;
|
|
644
|
+
const rawRes = res.body;
|
|
645
|
+
let payload;
|
|
646
|
+
try {
|
|
647
|
+
payload = typeof rawRes === "string" ? JSON.parse(rawRes) : rawRes;
|
|
648
|
+
}
|
|
649
|
+
catch {
|
|
650
|
+
payload = { raw: rawRes };
|
|
651
|
+
}
|
|
652
|
+
return { status, payload };
|
|
626
653
|
};
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
const status = res.statusCode;
|
|
641
|
-
const rawRes = res.body;
|
|
642
|
-
let payload;
|
|
643
|
-
try {
|
|
644
|
-
payload = typeof rawRes === "string" ? JSON.parse(rawRes) : rawRes;
|
|
645
|
-
}
|
|
646
|
-
catch {
|
|
647
|
-
payload = { raw: rawRes };
|
|
654
|
+
let rawBody = bodyObj === undefined ? "" : JSON.stringify(bodyObj);
|
|
655
|
+
let { status, payload } = await sendSigned(rawBody);
|
|
656
|
+
// Registrar conversa nunca deve falhar por causa de um pedido_id inválido
|
|
657
|
+
// (a IA pode mandar um UUID que não existe no tenant). Se o Núcleo recusar
|
|
658
|
+
// o pedido, reenvia sem ele — a conversa ainda é registrada.
|
|
659
|
+
if (status === 404 &&
|
|
660
|
+
resource === "conversa" &&
|
|
661
|
+
operation === "registrar" &&
|
|
662
|
+
bodyObj &&
|
|
663
|
+
bodyObj.pedido_id) {
|
|
664
|
+
delete bodyObj.pedido_id;
|
|
665
|
+
rawBody = JSON.stringify(bodyObj);
|
|
666
|
+
({ status, payload } = await sendSigned(rawBody));
|
|
648
667
|
}
|
|
649
668
|
if (status >= 400) {
|
|
650
669
|
const msg = (payload && payload.error) || `Núcleo respondeu HTTP ${status}.`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wondai/n8n-nodes-nucleo",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "Node n8n para o Núcleo Wondai — atendimento de IA (cliente, catálogo fuzzy, pedidos) com assinatura HMAC v1. Tenant vem do token (a parede, ADR-013).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|