@atomoz/workflows-nodes 0.1.27 → 0.1.28
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/index.cjs +378 -16
- package/dist/index.d.cts +40 -2
- package/dist/index.d.ts +40 -2
- package/dist/index.js +372 -16
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,13 @@ __export(index_exports, {
|
|
|
36
36
|
AiToolNodeFunction: () => AiToolNodeFunction,
|
|
37
37
|
AiToolNodeSchema: () => AiToolNodeSchema,
|
|
38
38
|
BodyFieldSchema: () => BodyFieldSchema,
|
|
39
|
+
ChatLogNode: () => ChatLogNode,
|
|
40
|
+
ChatLogNodeFunction: () => ChatLogNodeFunction,
|
|
41
|
+
ChatLogSchema: () => ChatLogSchema,
|
|
39
42
|
CustomToolSchema: () => CustomToolSchema,
|
|
43
|
+
GetOrCreateThreadNode: () => GetOrCreateThreadNode,
|
|
44
|
+
GetOrCreateThreadNodeFunction: () => GetOrCreateThreadNodeFunction,
|
|
45
|
+
GetOrCreateThreadSchema: () => GetOrCreateThreadSchema,
|
|
40
46
|
HTTP_METHODS: () => HTTP_METHODS,
|
|
41
47
|
HTTP_NODE_TYPES: () => HTTP_NODE_TYPES,
|
|
42
48
|
HeaderSchema: () => HeaderSchema,
|
|
@@ -1124,6 +1130,18 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
|
|
|
1124
1130
|
}
|
|
1125
1131
|
|
|
1126
1132
|
// src/utils/guardrail-executor.ts
|
|
1133
|
+
function emitGuardrailEvent(context, name, passed, action, details) {
|
|
1134
|
+
if (context?.emitter?.emitThought) {
|
|
1135
|
+
context.emitter.emitThought({
|
|
1136
|
+
content: `guardrail:${passed ? "passed" : "failed"}:${name}`,
|
|
1137
|
+
type: "guardrail",
|
|
1138
|
+
name,
|
|
1139
|
+
passed,
|
|
1140
|
+
action: action || "evaluate",
|
|
1141
|
+
details
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1127
1145
|
async function loadChatHistory(context) {
|
|
1128
1146
|
const checkpointer = context?.checkpointer;
|
|
1129
1147
|
const sessionId = context?.sessionId;
|
|
@@ -1218,6 +1236,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first", conte
|
|
|
1218
1236
|
if (!guardPassed && actionInstruction) {
|
|
1219
1237
|
violationMessage = actionInstruction;
|
|
1220
1238
|
}
|
|
1239
|
+
emitGuardrailEvent(context, guard.name, guardPassed, guard.action, violationMessage || "Rule passed");
|
|
1221
1240
|
} else if (guard.type === "function") {
|
|
1222
1241
|
const { nodeFunction, name, actionInstruction } = guard;
|
|
1223
1242
|
if (typeof nodeFunction === "function") {
|
|
@@ -1250,6 +1269,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first", conte
|
|
|
1250
1269
|
guardPassed = false;
|
|
1251
1270
|
violationMessage = `Erro na fun\xE7\xE3o guardrail: ${error instanceof Error ? error.message : String(error)}`;
|
|
1252
1271
|
}
|
|
1272
|
+
emitGuardrailEvent(context, name, guardPassed, guard.action, violationMessage || "Function passed");
|
|
1253
1273
|
}
|
|
1254
1274
|
} else if (guard.type === "model") {
|
|
1255
1275
|
const { model, evaluationPrompt, name, actionInstruction } = guard;
|
|
@@ -1317,6 +1337,7 @@ Reescreva o conte\xFAdo corrigindo a viola\xE7\xE3o. Retorne APENAS o texto corr
|
|
|
1317
1337
|
message: violationMessage,
|
|
1318
1338
|
action: "fix"
|
|
1319
1339
|
});
|
|
1340
|
+
emitGuardrailEvent(context, name, false, "fix", `Content fixed: ${fixedContent.slice(0, 100)}...`);
|
|
1320
1341
|
} catch (fixError) {
|
|
1321
1342
|
console.error(`[GUARDRAIL LLM] Erro ao corrigir conte\xFAdo:`, fixError);
|
|
1322
1343
|
}
|
|
@@ -1328,8 +1349,10 @@ Reescreva o conte\xFAdo corrigindo a viola\xE7\xE3o. Retorne APENAS o texto corr
|
|
|
1328
1349
|
guardPassed = false;
|
|
1329
1350
|
violationMessage = actionInstruction || `Modelo de avalia\xE7\xE3o "${name}" detectou viola\xE7\xE3o de seguran\xE7a/pol\xEDtica.`;
|
|
1330
1351
|
console.log(`[GUARDRAIL LLM] Resultado: UNSAFE - Bloqueado`);
|
|
1352
|
+
emitGuardrailEvent(context, name, false, guard.action, violationMessage);
|
|
1331
1353
|
} else {
|
|
1332
1354
|
console.log(`[GUARDRAIL LLM] Resultado: SAFE - Aprovado`);
|
|
1355
|
+
emitGuardrailEvent(context, name, true, "approve", "Content passed evaluation");
|
|
1333
1356
|
}
|
|
1334
1357
|
}
|
|
1335
1358
|
} catch (error) {
|
|
@@ -3307,6 +3330,335 @@ var ModelGuardrailNodeFunction = async (inputs) => {
|
|
|
3307
3330
|
};
|
|
3308
3331
|
};
|
|
3309
3332
|
|
|
3333
|
+
// src/nodes/chat/getOrCreateThread/data.ts
|
|
3334
|
+
var import_zod17 = require("zod");
|
|
3335
|
+
var GetOrCreateThreadSchema = import_zod17.z.object({
|
|
3336
|
+
source: import_zod17.z.string().describe("Channel source: whatsapp, telegram, web, etc."),
|
|
3337
|
+
identifier: import_zod17.z.string().describe("User identifier: phone number, chat_id, userId"),
|
|
3338
|
+
timeoutMinutes: import_zod17.z.number().optional().describe("Inactivity timeout in minutes (default: 1440 = 24h)")
|
|
3339
|
+
});
|
|
3340
|
+
var GetOrCreateThreadNode = {
|
|
3341
|
+
label: "Get or Create Thread",
|
|
3342
|
+
type: "GetOrCreateThreadNode",
|
|
3343
|
+
category: "chat",
|
|
3344
|
+
description: "Generates or retrieves a threadId based on identifier + timeout. Ensures tenant isolation.",
|
|
3345
|
+
icon: "\u{1F9F5}",
|
|
3346
|
+
group: "Chat",
|
|
3347
|
+
tags: {
|
|
3348
|
+
execution: "async",
|
|
3349
|
+
group: "Chat"
|
|
3350
|
+
},
|
|
3351
|
+
fields: [
|
|
3352
|
+
{
|
|
3353
|
+
id: "source",
|
|
3354
|
+
label: "Source",
|
|
3355
|
+
type: "string",
|
|
3356
|
+
required: true,
|
|
3357
|
+
defaultValue: "whatsapp",
|
|
3358
|
+
placeholder: "whatsapp, telegram, web",
|
|
3359
|
+
handle: {
|
|
3360
|
+
type: "input",
|
|
3361
|
+
label: "Source",
|
|
3362
|
+
name: "source",
|
|
3363
|
+
fieldType: "string"
|
|
3364
|
+
}
|
|
3365
|
+
},
|
|
3366
|
+
{
|
|
3367
|
+
id: "identifier",
|
|
3368
|
+
label: "Identifier",
|
|
3369
|
+
type: "string",
|
|
3370
|
+
required: true,
|
|
3371
|
+
placeholder: "+5511999999999",
|
|
3372
|
+
handle: {
|
|
3373
|
+
type: "input",
|
|
3374
|
+
label: "Identifier",
|
|
3375
|
+
name: "identifier",
|
|
3376
|
+
fieldType: "string"
|
|
3377
|
+
}
|
|
3378
|
+
},
|
|
3379
|
+
{
|
|
3380
|
+
id: "timeoutMinutes",
|
|
3381
|
+
label: "Timeout (minutes)",
|
|
3382
|
+
type: "number",
|
|
3383
|
+
required: false,
|
|
3384
|
+
defaultValue: "1440",
|
|
3385
|
+
placeholder: "1440 (24 hours)"
|
|
3386
|
+
},
|
|
3387
|
+
{
|
|
3388
|
+
id: "threadId",
|
|
3389
|
+
label: "Thread ID",
|
|
3390
|
+
type: "string",
|
|
3391
|
+
required: true,
|
|
3392
|
+
typeable: false,
|
|
3393
|
+
handle: {
|
|
3394
|
+
type: "output",
|
|
3395
|
+
label: "Thread ID",
|
|
3396
|
+
name: "threadId",
|
|
3397
|
+
fieldType: "string"
|
|
3398
|
+
}
|
|
3399
|
+
},
|
|
3400
|
+
{
|
|
3401
|
+
id: "isNew",
|
|
3402
|
+
label: "Is New Thread",
|
|
3403
|
+
type: "boolean",
|
|
3404
|
+
required: true,
|
|
3405
|
+
typeable: false,
|
|
3406
|
+
handle: {
|
|
3407
|
+
type: "output",
|
|
3408
|
+
label: "Is New",
|
|
3409
|
+
name: "isNew",
|
|
3410
|
+
fieldType: "boolean"
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
]
|
|
3414
|
+
};
|
|
3415
|
+
|
|
3416
|
+
// src/nodes/chat/getOrCreateThread/function.ts
|
|
3417
|
+
var GetOrCreateThreadNodeFunction = async (inputs) => {
|
|
3418
|
+
const fieldValues = inputs.fieldValues || {};
|
|
3419
|
+
const context = inputs.context || {};
|
|
3420
|
+
const source = fieldValues.source;
|
|
3421
|
+
const identifier = fieldValues.identifier;
|
|
3422
|
+
const timeoutMinutes = Number(fieldValues.timeoutMinutes) || 1440;
|
|
3423
|
+
const companyId = context?.companyId;
|
|
3424
|
+
if (!companyId) {
|
|
3425
|
+
throw new Error("GetOrCreateThread requires companyId in context for tenant isolation");
|
|
3426
|
+
}
|
|
3427
|
+
if (!source || !identifier) {
|
|
3428
|
+
throw new Error("GetOrCreateThread requires source and identifier");
|
|
3429
|
+
}
|
|
3430
|
+
const timeoutMs = timeoutMinutes * 60 * 1e3;
|
|
3431
|
+
const thresholdDate = new Date(Date.now() - timeoutMs);
|
|
3432
|
+
const db = context?.db;
|
|
3433
|
+
if (!db) {
|
|
3434
|
+
throw new Error("GetOrCreateThread requires database connection in context");
|
|
3435
|
+
}
|
|
3436
|
+
try {
|
|
3437
|
+
const existingSessions = await db.query(`
|
|
3438
|
+
SELECT id, session_id, updated_at
|
|
3439
|
+
FROM chat_sessions
|
|
3440
|
+
WHERE company_id = $1
|
|
3441
|
+
AND metadata->>'source' = $2
|
|
3442
|
+
AND metadata->>'identifier' = $3
|
|
3443
|
+
AND updated_at > $4
|
|
3444
|
+
ORDER BY updated_at DESC
|
|
3445
|
+
LIMIT 1
|
|
3446
|
+
`, [companyId, source, identifier, thresholdDate]);
|
|
3447
|
+
if (existingSessions.rows && existingSessions.rows.length > 0) {
|
|
3448
|
+
const session = existingSessions.rows[0];
|
|
3449
|
+
await db.query(`
|
|
3450
|
+
UPDATE chat_sessions
|
|
3451
|
+
SET updated_at = NOW()
|
|
3452
|
+
WHERE id = $1 AND company_id = $2
|
|
3453
|
+
`, [session.id, companyId]);
|
|
3454
|
+
return {
|
|
3455
|
+
threadId: session.session_id,
|
|
3456
|
+
isNew: false
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
const newSessionId = crypto.randomUUID();
|
|
3460
|
+
const workflowId = context?.workflowId;
|
|
3461
|
+
await db.query(`
|
|
3462
|
+
INSERT INTO chat_sessions (workflow_id, company_id, chat_id, session_id, metadata)
|
|
3463
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
3464
|
+
`, [
|
|
3465
|
+
workflowId || companyId,
|
|
3466
|
+
// fallback to companyId if no workflowId
|
|
3467
|
+
companyId,
|
|
3468
|
+
`${source}:${identifier}`,
|
|
3469
|
+
// chatId as composite key
|
|
3470
|
+
newSessionId,
|
|
3471
|
+
JSON.stringify({ source, identifier })
|
|
3472
|
+
]);
|
|
3473
|
+
return {
|
|
3474
|
+
threadId: newSessionId,
|
|
3475
|
+
isNew: true
|
|
3476
|
+
};
|
|
3477
|
+
} catch (error) {
|
|
3478
|
+
console.error("[GetOrCreateThread] Error:", error);
|
|
3479
|
+
throw error;
|
|
3480
|
+
}
|
|
3481
|
+
};
|
|
3482
|
+
|
|
3483
|
+
// src/nodes/chat/chatLog/data.ts
|
|
3484
|
+
var import_zod18 = require("zod");
|
|
3485
|
+
var ChatLogSchema = import_zod18.z.object({
|
|
3486
|
+
threadId: import_zod18.z.string().describe("Thread ID from GetOrCreateThread"),
|
|
3487
|
+
direction: import_zod18.z.enum(["inbound", "outbound"]).describe("Message direction"),
|
|
3488
|
+
content: import_zod18.z.string().describe("Message content"),
|
|
3489
|
+
source: import_zod18.z.string().optional().describe("Channel source"),
|
|
3490
|
+
identifier: import_zod18.z.string().optional().describe("User identifier"),
|
|
3491
|
+
metadata: import_zod18.z.record(import_zod18.z.string(), import_zod18.z.any()).optional().describe("Additional metadata")
|
|
3492
|
+
});
|
|
3493
|
+
var ChatLogNode = {
|
|
3494
|
+
label: "Chat Log",
|
|
3495
|
+
type: "ChatLogNode",
|
|
3496
|
+
category: "chat",
|
|
3497
|
+
description: "Saves a message to the chat history. Supports inbound (user) and outbound (assistant) messages.",
|
|
3498
|
+
icon: "\u{1F4AC}",
|
|
3499
|
+
group: "Chat",
|
|
3500
|
+
tags: {
|
|
3501
|
+
execution: "async",
|
|
3502
|
+
group: "Chat"
|
|
3503
|
+
},
|
|
3504
|
+
fields: [
|
|
3505
|
+
{
|
|
3506
|
+
id: "threadId",
|
|
3507
|
+
label: "Thread ID",
|
|
3508
|
+
type: "string",
|
|
3509
|
+
required: true,
|
|
3510
|
+
placeholder: "From GetOrCreateThread node",
|
|
3511
|
+
handle: {
|
|
3512
|
+
type: "input",
|
|
3513
|
+
label: "Thread ID",
|
|
3514
|
+
name: "threadId",
|
|
3515
|
+
fieldType: "string"
|
|
3516
|
+
}
|
|
3517
|
+
},
|
|
3518
|
+
{
|
|
3519
|
+
id: "direction",
|
|
3520
|
+
label: "Direction",
|
|
3521
|
+
type: "select",
|
|
3522
|
+
required: true,
|
|
3523
|
+
defaultValue: "inbound",
|
|
3524
|
+
options: [
|
|
3525
|
+
{ label: "Inbound (User \u2192 System)", value: "inbound" },
|
|
3526
|
+
{ label: "Outbound (System \u2192 User)", value: "outbound" }
|
|
3527
|
+
]
|
|
3528
|
+
},
|
|
3529
|
+
{
|
|
3530
|
+
id: "content",
|
|
3531
|
+
label: "Content",
|
|
3532
|
+
type: "string",
|
|
3533
|
+
required: true,
|
|
3534
|
+
placeholder: "Message content",
|
|
3535
|
+
handle: {
|
|
3536
|
+
type: "input",
|
|
3537
|
+
label: "Content",
|
|
3538
|
+
name: "content",
|
|
3539
|
+
fieldType: "string"
|
|
3540
|
+
}
|
|
3541
|
+
},
|
|
3542
|
+
{
|
|
3543
|
+
id: "source",
|
|
3544
|
+
label: "Source",
|
|
3545
|
+
type: "string",
|
|
3546
|
+
required: false,
|
|
3547
|
+
defaultValue: "whatsapp",
|
|
3548
|
+
placeholder: "whatsapp, telegram, web",
|
|
3549
|
+
handle: {
|
|
3550
|
+
type: "input",
|
|
3551
|
+
label: "Source",
|
|
3552
|
+
name: "source",
|
|
3553
|
+
fieldType: "string"
|
|
3554
|
+
}
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
id: "identifier",
|
|
3558
|
+
label: "Identifier",
|
|
3559
|
+
type: "string",
|
|
3560
|
+
required: false,
|
|
3561
|
+
placeholder: "+5511999999999",
|
|
3562
|
+
handle: {
|
|
3563
|
+
type: "input",
|
|
3564
|
+
label: "Identifier",
|
|
3565
|
+
name: "identifier",
|
|
3566
|
+
fieldType: "string"
|
|
3567
|
+
}
|
|
3568
|
+
},
|
|
3569
|
+
{
|
|
3570
|
+
id: "messageId",
|
|
3571
|
+
label: "Message ID",
|
|
3572
|
+
type: "string",
|
|
3573
|
+
required: true,
|
|
3574
|
+
typeable: false,
|
|
3575
|
+
handle: {
|
|
3576
|
+
type: "output",
|
|
3577
|
+
label: "Message ID",
|
|
3578
|
+
name: "messageId",
|
|
3579
|
+
fieldType: "string"
|
|
3580
|
+
}
|
|
3581
|
+
},
|
|
3582
|
+
{
|
|
3583
|
+
id: "success",
|
|
3584
|
+
label: "Success",
|
|
3585
|
+
type: "boolean",
|
|
3586
|
+
required: true,
|
|
3587
|
+
typeable: false,
|
|
3588
|
+
handle: {
|
|
3589
|
+
type: "output",
|
|
3590
|
+
label: "Success",
|
|
3591
|
+
name: "success",
|
|
3592
|
+
fieldType: "boolean"
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
]
|
|
3596
|
+
};
|
|
3597
|
+
|
|
3598
|
+
// src/nodes/chat/chatLog/function.ts
|
|
3599
|
+
var ChatLogNodeFunction = async (inputs) => {
|
|
3600
|
+
const fieldValues = inputs.fieldValues || {};
|
|
3601
|
+
const context = inputs.context || {};
|
|
3602
|
+
const threadId = fieldValues.threadId;
|
|
3603
|
+
const direction = fieldValues.direction;
|
|
3604
|
+
const content = fieldValues.content;
|
|
3605
|
+
const source = fieldValues.source;
|
|
3606
|
+
const identifier = fieldValues.identifier;
|
|
3607
|
+
const companyId = context?.companyId;
|
|
3608
|
+
if (!companyId) {
|
|
3609
|
+
throw new Error("ChatLog requires companyId in context for tenant isolation");
|
|
3610
|
+
}
|
|
3611
|
+
if (!threadId || !content) {
|
|
3612
|
+
throw new Error("ChatLog requires threadId and content");
|
|
3613
|
+
}
|
|
3614
|
+
const role = direction === "inbound" ? "user" : "assistant";
|
|
3615
|
+
const db = context?.db;
|
|
3616
|
+
if (!db) {
|
|
3617
|
+
throw new Error("ChatLog requires database connection in context");
|
|
3618
|
+
}
|
|
3619
|
+
try {
|
|
3620
|
+
const sessionResult = await db.query(`
|
|
3621
|
+
SELECT id FROM chat_sessions
|
|
3622
|
+
WHERE session_id = $1 AND company_id = $2
|
|
3623
|
+
LIMIT 1
|
|
3624
|
+
`, [threadId, companyId]);
|
|
3625
|
+
if (!sessionResult.rows || sessionResult.rows.length === 0) {
|
|
3626
|
+
throw new Error(`Session not found for threadId: ${threadId}`);
|
|
3627
|
+
}
|
|
3628
|
+
const sessionId = sessionResult.rows[0].id;
|
|
3629
|
+
const messageId = crypto.randomUUID();
|
|
3630
|
+
await db.query(`
|
|
3631
|
+
INSERT INTO chat_messages (id, session_id, role, content, metadata)
|
|
3632
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
3633
|
+
`, [
|
|
3634
|
+
messageId,
|
|
3635
|
+
sessionId,
|
|
3636
|
+
role,
|
|
3637
|
+
content,
|
|
3638
|
+
JSON.stringify({
|
|
3639
|
+
direction,
|
|
3640
|
+
source: source || null,
|
|
3641
|
+
identifier: identifier || null
|
|
3642
|
+
})
|
|
3643
|
+
]);
|
|
3644
|
+
await db.query(`
|
|
3645
|
+
UPDATE chat_sessions
|
|
3646
|
+
SET updated_at = NOW()
|
|
3647
|
+
WHERE id = $1 AND company_id = $2
|
|
3648
|
+
`, [sessionId, companyId]);
|
|
3649
|
+
return {
|
|
3650
|
+
messageId,
|
|
3651
|
+
success: true
|
|
3652
|
+
};
|
|
3653
|
+
} catch (error) {
|
|
3654
|
+
console.error("[ChatLog] Error:", error);
|
|
3655
|
+
return {
|
|
3656
|
+
messageId: null,
|
|
3657
|
+
success: false
|
|
3658
|
+
};
|
|
3659
|
+
}
|
|
3660
|
+
};
|
|
3661
|
+
|
|
3310
3662
|
// src/nodes/consts/nodes.ts
|
|
3311
3663
|
var nodes = [
|
|
3312
3664
|
ChatInputNode,
|
|
@@ -3333,7 +3685,9 @@ var nodes = [
|
|
|
3333
3685
|
PromptGuardrailNode,
|
|
3334
3686
|
RuleGuardrailNode,
|
|
3335
3687
|
FunctionGuardrailNode,
|
|
3336
|
-
ModelGuardrailNode
|
|
3688
|
+
ModelGuardrailNode,
|
|
3689
|
+
GetOrCreateThreadNode,
|
|
3690
|
+
ChatLogNode
|
|
3337
3691
|
];
|
|
3338
3692
|
var nodes_default = nodes;
|
|
3339
3693
|
|
|
@@ -3455,7 +3809,9 @@ var nodeFunctions = {
|
|
|
3455
3809
|
PromptGuardrailNode: PromptGuardrailNodeFunction,
|
|
3456
3810
|
RuleGuardrailNode: RuleGuardrailNodeFunction,
|
|
3457
3811
|
FunctionGuardrailNode: FunctionGuardrailNodeFunction,
|
|
3458
|
-
ModelGuardrailNode: ModelGuardrailNodeFunction
|
|
3812
|
+
ModelGuardrailNode: ModelGuardrailNodeFunction,
|
|
3813
|
+
GetOrCreateThreadNode: GetOrCreateThreadNodeFunction,
|
|
3814
|
+
ChatLogNode: ChatLogNodeFunction
|
|
3459
3815
|
};
|
|
3460
3816
|
var node_functions_default = nodeFunctions;
|
|
3461
3817
|
|
|
@@ -3569,12 +3925,12 @@ var HttpPutInputNodeFunction = (params) => {
|
|
|
3569
3925
|
};
|
|
3570
3926
|
|
|
3571
3927
|
// src/nodes/inputs/http/put/schema.ts
|
|
3572
|
-
var
|
|
3573
|
-
var HttpPutInputNodeSchema =
|
|
3928
|
+
var import_zod19 = require("zod");
|
|
3929
|
+
var HttpPutInputNodeSchema = import_zod19.z.object({
|
|
3574
3930
|
route: RouteSchema,
|
|
3575
|
-
queryParams:
|
|
3576
|
-
headers:
|
|
3577
|
-
body:
|
|
3931
|
+
queryParams: import_zod19.z.array(QueryParamSchema).optional().describe("Query parameters configuration"),
|
|
3932
|
+
headers: import_zod19.z.array(HeaderSchema).optional().describe("Headers configuration"),
|
|
3933
|
+
body: import_zod19.z.array(BodyFieldSchema).optional().describe("Body fields configuration")
|
|
3578
3934
|
});
|
|
3579
3935
|
|
|
3580
3936
|
// src/nodes/inputs/http/delete/data.ts
|
|
@@ -3666,11 +4022,11 @@ var HttpDeleteInputNodeFunction = async (params) => {
|
|
|
3666
4022
|
};
|
|
3667
4023
|
|
|
3668
4024
|
// src/nodes/inputs/http/delete/schema.ts
|
|
3669
|
-
var
|
|
3670
|
-
var HttpDeleteInputNodeSchema =
|
|
4025
|
+
var import_zod20 = require("zod");
|
|
4026
|
+
var HttpDeleteInputNodeSchema = import_zod20.z.object({
|
|
3671
4027
|
route: RouteSchema,
|
|
3672
|
-
queryParams:
|
|
3673
|
-
headers:
|
|
4028
|
+
queryParams: import_zod20.z.array(QueryParamSchema).optional().describe("Query parameters configuration"),
|
|
4029
|
+
headers: import_zod20.z.array(HeaderSchema).optional().describe("Headers configuration")
|
|
3674
4030
|
});
|
|
3675
4031
|
|
|
3676
4032
|
// src/nodes/inputs/http/patch/data.ts
|
|
@@ -3783,12 +4139,12 @@ var HttpPatchInputNodeFunction = (params) => {
|
|
|
3783
4139
|
};
|
|
3784
4140
|
|
|
3785
4141
|
// src/nodes/inputs/http/patch/schema.ts
|
|
3786
|
-
var
|
|
3787
|
-
var HttpPatchInputNodeSchema =
|
|
4142
|
+
var import_zod21 = require("zod");
|
|
4143
|
+
var HttpPatchInputNodeSchema = import_zod21.z.object({
|
|
3788
4144
|
route: RouteSchema,
|
|
3789
|
-
queryParams:
|
|
3790
|
-
headers:
|
|
3791
|
-
body:
|
|
4145
|
+
queryParams: import_zod21.z.array(QueryParamSchema).optional().describe("Query parameters configuration"),
|
|
4146
|
+
headers: import_zod21.z.array(HeaderSchema).optional().describe("Headers configuration"),
|
|
4147
|
+
body: import_zod21.z.array(BodyFieldSchema).optional().describe("Body fields configuration")
|
|
3792
4148
|
});
|
|
3793
4149
|
|
|
3794
4150
|
// src/nodes/inputs/http/utils.ts
|
|
@@ -3848,7 +4204,13 @@ var getHttpMethodFromFriendlyId = (friendlyId) => {
|
|
|
3848
4204
|
AiToolNodeFunction,
|
|
3849
4205
|
AiToolNodeSchema,
|
|
3850
4206
|
BodyFieldSchema,
|
|
4207
|
+
ChatLogNode,
|
|
4208
|
+
ChatLogNodeFunction,
|
|
4209
|
+
ChatLogSchema,
|
|
3851
4210
|
CustomToolSchema,
|
|
4211
|
+
GetOrCreateThreadNode,
|
|
4212
|
+
GetOrCreateThreadNodeFunction,
|
|
4213
|
+
GetOrCreateThreadSchema,
|
|
3852
4214
|
HTTP_METHODS,
|
|
3853
4215
|
HTTP_NODE_TYPES,
|
|
3854
4216
|
HeaderSchema,
|
package/dist/index.d.cts
CHANGED
|
@@ -144,7 +144,7 @@ interface ExecutionStep {
|
|
|
144
144
|
type NodeExecution = 'sync' | 'async';
|
|
145
145
|
interface NodeTags {
|
|
146
146
|
execution: NodeExecution[] | NodeExecution;
|
|
147
|
-
group: 'IA' | 'HTTP' | 'Data Transformation' | 'Custom' | 'Social' | 'Control' | 'Memory' | 'Guardrails';
|
|
147
|
+
group: 'IA' | 'HTTP' | 'Data Transformation' | 'Custom' | 'Social' | 'Control' | 'Memory' | 'Guardrails' | 'Chat';
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
type NodeData = {
|
|
@@ -191,6 +191,8 @@ declare const nodeFunctions: {
|
|
|
191
191
|
RuleGuardrailNode: (inputs: any) => Promise<any>;
|
|
192
192
|
FunctionGuardrailNode: (inputs: any) => Promise<any>;
|
|
193
193
|
ModelGuardrailNode: (inputs: any) => Promise<any>;
|
|
194
|
+
GetOrCreateThreadNode: (inputs: any) => Promise<any>;
|
|
195
|
+
ChatLogNode: (inputs: any) => Promise<any>;
|
|
194
196
|
};
|
|
195
197
|
|
|
196
198
|
declare const IaAgentNodeSchema: z.ZodObject<{
|
|
@@ -444,4 +446,40 @@ declare const WhatsappSendMessageFunction: (fieldValues: any) => Promise<any>;
|
|
|
444
446
|
|
|
445
447
|
declare const WhatsappMessageTriggerNode: NodeData;
|
|
446
448
|
|
|
447
|
-
|
|
449
|
+
declare const GetOrCreateThreadSchema: z.ZodObject<{
|
|
450
|
+
source: z.ZodString;
|
|
451
|
+
identifier: z.ZodString;
|
|
452
|
+
timeoutMinutes: z.ZodOptional<z.ZodNumber>;
|
|
453
|
+
}, z.core.$strip>;
|
|
454
|
+
declare const GetOrCreateThreadNode: NodeData;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* GetOrCreateThread Node Function
|
|
458
|
+
*
|
|
459
|
+
* Generates or retrieves a threadId based on source + identifier + timeout.
|
|
460
|
+
* ALWAYS filters by companyId for tenant isolation.
|
|
461
|
+
*/
|
|
462
|
+
declare const GetOrCreateThreadNodeFunction: (inputs: any) => Promise<any>;
|
|
463
|
+
|
|
464
|
+
declare const ChatLogSchema: z.ZodObject<{
|
|
465
|
+
threadId: z.ZodString;
|
|
466
|
+
direction: z.ZodEnum<{
|
|
467
|
+
inbound: "inbound";
|
|
468
|
+
outbound: "outbound";
|
|
469
|
+
}>;
|
|
470
|
+
content: z.ZodString;
|
|
471
|
+
source: z.ZodOptional<z.ZodString>;
|
|
472
|
+
identifier: z.ZodOptional<z.ZodString>;
|
|
473
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
474
|
+
}, z.core.$strip>;
|
|
475
|
+
declare const ChatLogNode: NodeData;
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* ChatLog Node Function
|
|
479
|
+
*
|
|
480
|
+
* Saves a message to chat_messages table.
|
|
481
|
+
* ALWAYS filters by companyId for tenant isolation.
|
|
482
|
+
*/
|
|
483
|
+
declare const ChatLogNodeFunction: (inputs: any) => Promise<any>;
|
|
484
|
+
|
|
485
|
+
export { AiSupervisorNode, AiSupervisorNodeFunction, AiSupervisorNodeSchema, AiToolNode, AiToolNodeFunction, AiToolNodeSchema, type BaseNodeType, BodyFieldSchema, ChatLogNode, ChatLogNodeFunction, ChatLogSchema, CustomToolSchema, type ExecutionStep, GetOrCreateThreadNode, GetOrCreateThreadNodeFunction, GetOrCreateThreadSchema, HTTP_METHODS, HTTP_NODE_TYPES, HeaderSchema, HttpDeleteInputNode, HttpDeleteInputNodeFunction, HttpDeleteInputNodeSchema, type HttpDeleteInputNodeType, HttpGetInputNode, HttpGetInputNodeFunction, HttpGetInputNodeSchema, type HttpGetInputNodeType, type HttpMethod, type HttpNodeType, type HttpOutput, HttpPatchInputNode, HttpPatchInputNodeFunction, HttpPatchInputNodeSchema, type HttpPatchInputNodeType, HttpPostInputNode, HttpPostInputNodeFunction, HttpPostInputNodeSchema, type HttpPostInputNodeType, HttpPutInputNode, HttpPutInputNodeFunction, HttpPutInputNodeSchema, type HttpPutInputNodeType, IaAgentNode, IaAgentNodeFunction, IaAgentNodeSchema, IaMessageNode, IaMessageNodeFunction, IaMessageNodeSchema, type NodeData, type NodeDefinition, type NodeExecution, type NodeExecutionConfig, type NodeExecutionContext, type NodeField, type NodeHandle, type NodeInput, type NodeInputValue, type NodeLogicFunction, type NodeOutput, type NodeOutputValue, type NodeStyle, type NodeTags, type NodeTransformation, type NodeValidation, QueryParamSchema, RouteSchema, WhatsappMessageTriggerNode, WhatsappSendMessageFunction, WhatsappSendMessageNode, WhatsappSendMessageNodeSchema, WhatsappSendTemplateNode, WhatsappSendTemplateNodeSchema, WhatsappStartChatFunction, createMessageTemplate, extractHttpMethodFromNodeType, getHttpMethodFromFriendlyId, getHttpMethodFromNodeType, getHttpNodeTypeStrings, getHttpNodeTypesArray, getHttpNodesTypes, getMessageTemplates, isAnyHttpInputNode, isHttpInputFriendlyId, isHttpInputNode, isHttpMethodNode, nodeFunctions, nodes, schemas };
|
package/dist/index.d.ts
CHANGED
|
@@ -144,7 +144,7 @@ interface ExecutionStep {
|
|
|
144
144
|
type NodeExecution = 'sync' | 'async';
|
|
145
145
|
interface NodeTags {
|
|
146
146
|
execution: NodeExecution[] | NodeExecution;
|
|
147
|
-
group: 'IA' | 'HTTP' | 'Data Transformation' | 'Custom' | 'Social' | 'Control' | 'Memory' | 'Guardrails';
|
|
147
|
+
group: 'IA' | 'HTTP' | 'Data Transformation' | 'Custom' | 'Social' | 'Control' | 'Memory' | 'Guardrails' | 'Chat';
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
type NodeData = {
|
|
@@ -191,6 +191,8 @@ declare const nodeFunctions: {
|
|
|
191
191
|
RuleGuardrailNode: (inputs: any) => Promise<any>;
|
|
192
192
|
FunctionGuardrailNode: (inputs: any) => Promise<any>;
|
|
193
193
|
ModelGuardrailNode: (inputs: any) => Promise<any>;
|
|
194
|
+
GetOrCreateThreadNode: (inputs: any) => Promise<any>;
|
|
195
|
+
ChatLogNode: (inputs: any) => Promise<any>;
|
|
194
196
|
};
|
|
195
197
|
|
|
196
198
|
declare const IaAgentNodeSchema: z.ZodObject<{
|
|
@@ -444,4 +446,40 @@ declare const WhatsappSendMessageFunction: (fieldValues: any) => Promise<any>;
|
|
|
444
446
|
|
|
445
447
|
declare const WhatsappMessageTriggerNode: NodeData;
|
|
446
448
|
|
|
447
|
-
|
|
449
|
+
declare const GetOrCreateThreadSchema: z.ZodObject<{
|
|
450
|
+
source: z.ZodString;
|
|
451
|
+
identifier: z.ZodString;
|
|
452
|
+
timeoutMinutes: z.ZodOptional<z.ZodNumber>;
|
|
453
|
+
}, z.core.$strip>;
|
|
454
|
+
declare const GetOrCreateThreadNode: NodeData;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* GetOrCreateThread Node Function
|
|
458
|
+
*
|
|
459
|
+
* Generates or retrieves a threadId based on source + identifier + timeout.
|
|
460
|
+
* ALWAYS filters by companyId for tenant isolation.
|
|
461
|
+
*/
|
|
462
|
+
declare const GetOrCreateThreadNodeFunction: (inputs: any) => Promise<any>;
|
|
463
|
+
|
|
464
|
+
declare const ChatLogSchema: z.ZodObject<{
|
|
465
|
+
threadId: z.ZodString;
|
|
466
|
+
direction: z.ZodEnum<{
|
|
467
|
+
inbound: "inbound";
|
|
468
|
+
outbound: "outbound";
|
|
469
|
+
}>;
|
|
470
|
+
content: z.ZodString;
|
|
471
|
+
source: z.ZodOptional<z.ZodString>;
|
|
472
|
+
identifier: z.ZodOptional<z.ZodString>;
|
|
473
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
474
|
+
}, z.core.$strip>;
|
|
475
|
+
declare const ChatLogNode: NodeData;
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* ChatLog Node Function
|
|
479
|
+
*
|
|
480
|
+
* Saves a message to chat_messages table.
|
|
481
|
+
* ALWAYS filters by companyId for tenant isolation.
|
|
482
|
+
*/
|
|
483
|
+
declare const ChatLogNodeFunction: (inputs: any) => Promise<any>;
|
|
484
|
+
|
|
485
|
+
export { AiSupervisorNode, AiSupervisorNodeFunction, AiSupervisorNodeSchema, AiToolNode, AiToolNodeFunction, AiToolNodeSchema, type BaseNodeType, BodyFieldSchema, ChatLogNode, ChatLogNodeFunction, ChatLogSchema, CustomToolSchema, type ExecutionStep, GetOrCreateThreadNode, GetOrCreateThreadNodeFunction, GetOrCreateThreadSchema, HTTP_METHODS, HTTP_NODE_TYPES, HeaderSchema, HttpDeleteInputNode, HttpDeleteInputNodeFunction, HttpDeleteInputNodeSchema, type HttpDeleteInputNodeType, HttpGetInputNode, HttpGetInputNodeFunction, HttpGetInputNodeSchema, type HttpGetInputNodeType, type HttpMethod, type HttpNodeType, type HttpOutput, HttpPatchInputNode, HttpPatchInputNodeFunction, HttpPatchInputNodeSchema, type HttpPatchInputNodeType, HttpPostInputNode, HttpPostInputNodeFunction, HttpPostInputNodeSchema, type HttpPostInputNodeType, HttpPutInputNode, HttpPutInputNodeFunction, HttpPutInputNodeSchema, type HttpPutInputNodeType, IaAgentNode, IaAgentNodeFunction, IaAgentNodeSchema, IaMessageNode, IaMessageNodeFunction, IaMessageNodeSchema, type NodeData, type NodeDefinition, type NodeExecution, type NodeExecutionConfig, type NodeExecutionContext, type NodeField, type NodeHandle, type NodeInput, type NodeInputValue, type NodeLogicFunction, type NodeOutput, type NodeOutputValue, type NodeStyle, type NodeTags, type NodeTransformation, type NodeValidation, QueryParamSchema, RouteSchema, WhatsappMessageTriggerNode, WhatsappSendMessageFunction, WhatsappSendMessageNode, WhatsappSendMessageNodeSchema, WhatsappSendTemplateNode, WhatsappSendTemplateNodeSchema, WhatsappStartChatFunction, createMessageTemplate, extractHttpMethodFromNodeType, getHttpMethodFromFriendlyId, getHttpMethodFromNodeType, getHttpNodeTypeStrings, getHttpNodeTypesArray, getHttpNodesTypes, getMessageTemplates, isAnyHttpInputNode, isHttpInputFriendlyId, isHttpInputNode, isHttpMethodNode, nodeFunctions, nodes, schemas };
|
package/dist/index.js
CHANGED
|
@@ -1034,6 +1034,18 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
|
|
|
1034
1034
|
}
|
|
1035
1035
|
|
|
1036
1036
|
// src/utils/guardrail-executor.ts
|
|
1037
|
+
function emitGuardrailEvent(context, name, passed, action, details) {
|
|
1038
|
+
if (context?.emitter?.emitThought) {
|
|
1039
|
+
context.emitter.emitThought({
|
|
1040
|
+
content: `guardrail:${passed ? "passed" : "failed"}:${name}`,
|
|
1041
|
+
type: "guardrail",
|
|
1042
|
+
name,
|
|
1043
|
+
passed,
|
|
1044
|
+
action: action || "evaluate",
|
|
1045
|
+
details
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1037
1049
|
async function loadChatHistory(context) {
|
|
1038
1050
|
const checkpointer = context?.checkpointer;
|
|
1039
1051
|
const sessionId = context?.sessionId;
|
|
@@ -1128,6 +1140,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first", conte
|
|
|
1128
1140
|
if (!guardPassed && actionInstruction) {
|
|
1129
1141
|
violationMessage = actionInstruction;
|
|
1130
1142
|
}
|
|
1143
|
+
emitGuardrailEvent(context, guard.name, guardPassed, guard.action, violationMessage || "Rule passed");
|
|
1131
1144
|
} else if (guard.type === "function") {
|
|
1132
1145
|
const { nodeFunction, name, actionInstruction } = guard;
|
|
1133
1146
|
if (typeof nodeFunction === "function") {
|
|
@@ -1160,6 +1173,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first", conte
|
|
|
1160
1173
|
guardPassed = false;
|
|
1161
1174
|
violationMessage = `Erro na fun\xE7\xE3o guardrail: ${error instanceof Error ? error.message : String(error)}`;
|
|
1162
1175
|
}
|
|
1176
|
+
emitGuardrailEvent(context, name, guardPassed, guard.action, violationMessage || "Function passed");
|
|
1163
1177
|
}
|
|
1164
1178
|
} else if (guard.type === "model") {
|
|
1165
1179
|
const { model, evaluationPrompt, name, actionInstruction } = guard;
|
|
@@ -1227,6 +1241,7 @@ Reescreva o conte\xFAdo corrigindo a viola\xE7\xE3o. Retorne APENAS o texto corr
|
|
|
1227
1241
|
message: violationMessage,
|
|
1228
1242
|
action: "fix"
|
|
1229
1243
|
});
|
|
1244
|
+
emitGuardrailEvent(context, name, false, "fix", `Content fixed: ${fixedContent.slice(0, 100)}...`);
|
|
1230
1245
|
} catch (fixError) {
|
|
1231
1246
|
console.error(`[GUARDRAIL LLM] Erro ao corrigir conte\xFAdo:`, fixError);
|
|
1232
1247
|
}
|
|
@@ -1238,8 +1253,10 @@ Reescreva o conte\xFAdo corrigindo a viola\xE7\xE3o. Retorne APENAS o texto corr
|
|
|
1238
1253
|
guardPassed = false;
|
|
1239
1254
|
violationMessage = actionInstruction || `Modelo de avalia\xE7\xE3o "${name}" detectou viola\xE7\xE3o de seguran\xE7a/pol\xEDtica.`;
|
|
1240
1255
|
console.log(`[GUARDRAIL LLM] Resultado: UNSAFE - Bloqueado`);
|
|
1256
|
+
emitGuardrailEvent(context, name, false, guard.action, violationMessage);
|
|
1241
1257
|
} else {
|
|
1242
1258
|
console.log(`[GUARDRAIL LLM] Resultado: SAFE - Aprovado`);
|
|
1259
|
+
emitGuardrailEvent(context, name, true, "approve", "Content passed evaluation");
|
|
1243
1260
|
}
|
|
1244
1261
|
}
|
|
1245
1262
|
} catch (error) {
|
|
@@ -3217,6 +3234,335 @@ var ModelGuardrailNodeFunction = async (inputs) => {
|
|
|
3217
3234
|
};
|
|
3218
3235
|
};
|
|
3219
3236
|
|
|
3237
|
+
// src/nodes/chat/getOrCreateThread/data.ts
|
|
3238
|
+
import { z as z17 } from "zod";
|
|
3239
|
+
var GetOrCreateThreadSchema = z17.object({
|
|
3240
|
+
source: z17.string().describe("Channel source: whatsapp, telegram, web, etc."),
|
|
3241
|
+
identifier: z17.string().describe("User identifier: phone number, chat_id, userId"),
|
|
3242
|
+
timeoutMinutes: z17.number().optional().describe("Inactivity timeout in minutes (default: 1440 = 24h)")
|
|
3243
|
+
});
|
|
3244
|
+
var GetOrCreateThreadNode = {
|
|
3245
|
+
label: "Get or Create Thread",
|
|
3246
|
+
type: "GetOrCreateThreadNode",
|
|
3247
|
+
category: "chat",
|
|
3248
|
+
description: "Generates or retrieves a threadId based on identifier + timeout. Ensures tenant isolation.",
|
|
3249
|
+
icon: "\u{1F9F5}",
|
|
3250
|
+
group: "Chat",
|
|
3251
|
+
tags: {
|
|
3252
|
+
execution: "async",
|
|
3253
|
+
group: "Chat"
|
|
3254
|
+
},
|
|
3255
|
+
fields: [
|
|
3256
|
+
{
|
|
3257
|
+
id: "source",
|
|
3258
|
+
label: "Source",
|
|
3259
|
+
type: "string",
|
|
3260
|
+
required: true,
|
|
3261
|
+
defaultValue: "whatsapp",
|
|
3262
|
+
placeholder: "whatsapp, telegram, web",
|
|
3263
|
+
handle: {
|
|
3264
|
+
type: "input",
|
|
3265
|
+
label: "Source",
|
|
3266
|
+
name: "source",
|
|
3267
|
+
fieldType: "string"
|
|
3268
|
+
}
|
|
3269
|
+
},
|
|
3270
|
+
{
|
|
3271
|
+
id: "identifier",
|
|
3272
|
+
label: "Identifier",
|
|
3273
|
+
type: "string",
|
|
3274
|
+
required: true,
|
|
3275
|
+
placeholder: "+5511999999999",
|
|
3276
|
+
handle: {
|
|
3277
|
+
type: "input",
|
|
3278
|
+
label: "Identifier",
|
|
3279
|
+
name: "identifier",
|
|
3280
|
+
fieldType: "string"
|
|
3281
|
+
}
|
|
3282
|
+
},
|
|
3283
|
+
{
|
|
3284
|
+
id: "timeoutMinutes",
|
|
3285
|
+
label: "Timeout (minutes)",
|
|
3286
|
+
type: "number",
|
|
3287
|
+
required: false,
|
|
3288
|
+
defaultValue: "1440",
|
|
3289
|
+
placeholder: "1440 (24 hours)"
|
|
3290
|
+
},
|
|
3291
|
+
{
|
|
3292
|
+
id: "threadId",
|
|
3293
|
+
label: "Thread ID",
|
|
3294
|
+
type: "string",
|
|
3295
|
+
required: true,
|
|
3296
|
+
typeable: false,
|
|
3297
|
+
handle: {
|
|
3298
|
+
type: "output",
|
|
3299
|
+
label: "Thread ID",
|
|
3300
|
+
name: "threadId",
|
|
3301
|
+
fieldType: "string"
|
|
3302
|
+
}
|
|
3303
|
+
},
|
|
3304
|
+
{
|
|
3305
|
+
id: "isNew",
|
|
3306
|
+
label: "Is New Thread",
|
|
3307
|
+
type: "boolean",
|
|
3308
|
+
required: true,
|
|
3309
|
+
typeable: false,
|
|
3310
|
+
handle: {
|
|
3311
|
+
type: "output",
|
|
3312
|
+
label: "Is New",
|
|
3313
|
+
name: "isNew",
|
|
3314
|
+
fieldType: "boolean"
|
|
3315
|
+
}
|
|
3316
|
+
}
|
|
3317
|
+
]
|
|
3318
|
+
};
|
|
3319
|
+
|
|
3320
|
+
// src/nodes/chat/getOrCreateThread/function.ts
|
|
3321
|
+
var GetOrCreateThreadNodeFunction = async (inputs) => {
|
|
3322
|
+
const fieldValues = inputs.fieldValues || {};
|
|
3323
|
+
const context = inputs.context || {};
|
|
3324
|
+
const source = fieldValues.source;
|
|
3325
|
+
const identifier = fieldValues.identifier;
|
|
3326
|
+
const timeoutMinutes = Number(fieldValues.timeoutMinutes) || 1440;
|
|
3327
|
+
const companyId = context?.companyId;
|
|
3328
|
+
if (!companyId) {
|
|
3329
|
+
throw new Error("GetOrCreateThread requires companyId in context for tenant isolation");
|
|
3330
|
+
}
|
|
3331
|
+
if (!source || !identifier) {
|
|
3332
|
+
throw new Error("GetOrCreateThread requires source and identifier");
|
|
3333
|
+
}
|
|
3334
|
+
const timeoutMs = timeoutMinutes * 60 * 1e3;
|
|
3335
|
+
const thresholdDate = new Date(Date.now() - timeoutMs);
|
|
3336
|
+
const db = context?.db;
|
|
3337
|
+
if (!db) {
|
|
3338
|
+
throw new Error("GetOrCreateThread requires database connection in context");
|
|
3339
|
+
}
|
|
3340
|
+
try {
|
|
3341
|
+
const existingSessions = await db.query(`
|
|
3342
|
+
SELECT id, session_id, updated_at
|
|
3343
|
+
FROM chat_sessions
|
|
3344
|
+
WHERE company_id = $1
|
|
3345
|
+
AND metadata->>'source' = $2
|
|
3346
|
+
AND metadata->>'identifier' = $3
|
|
3347
|
+
AND updated_at > $4
|
|
3348
|
+
ORDER BY updated_at DESC
|
|
3349
|
+
LIMIT 1
|
|
3350
|
+
`, [companyId, source, identifier, thresholdDate]);
|
|
3351
|
+
if (existingSessions.rows && existingSessions.rows.length > 0) {
|
|
3352
|
+
const session = existingSessions.rows[0];
|
|
3353
|
+
await db.query(`
|
|
3354
|
+
UPDATE chat_sessions
|
|
3355
|
+
SET updated_at = NOW()
|
|
3356
|
+
WHERE id = $1 AND company_id = $2
|
|
3357
|
+
`, [session.id, companyId]);
|
|
3358
|
+
return {
|
|
3359
|
+
threadId: session.session_id,
|
|
3360
|
+
isNew: false
|
|
3361
|
+
};
|
|
3362
|
+
}
|
|
3363
|
+
const newSessionId = crypto.randomUUID();
|
|
3364
|
+
const workflowId = context?.workflowId;
|
|
3365
|
+
await db.query(`
|
|
3366
|
+
INSERT INTO chat_sessions (workflow_id, company_id, chat_id, session_id, metadata)
|
|
3367
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
3368
|
+
`, [
|
|
3369
|
+
workflowId || companyId,
|
|
3370
|
+
// fallback to companyId if no workflowId
|
|
3371
|
+
companyId,
|
|
3372
|
+
`${source}:${identifier}`,
|
|
3373
|
+
// chatId as composite key
|
|
3374
|
+
newSessionId,
|
|
3375
|
+
JSON.stringify({ source, identifier })
|
|
3376
|
+
]);
|
|
3377
|
+
return {
|
|
3378
|
+
threadId: newSessionId,
|
|
3379
|
+
isNew: true
|
|
3380
|
+
};
|
|
3381
|
+
} catch (error) {
|
|
3382
|
+
console.error("[GetOrCreateThread] Error:", error);
|
|
3383
|
+
throw error;
|
|
3384
|
+
}
|
|
3385
|
+
};
|
|
3386
|
+
|
|
3387
|
+
// src/nodes/chat/chatLog/data.ts
|
|
3388
|
+
import { z as z18 } from "zod";
|
|
3389
|
+
var ChatLogSchema = z18.object({
|
|
3390
|
+
threadId: z18.string().describe("Thread ID from GetOrCreateThread"),
|
|
3391
|
+
direction: z18.enum(["inbound", "outbound"]).describe("Message direction"),
|
|
3392
|
+
content: z18.string().describe("Message content"),
|
|
3393
|
+
source: z18.string().optional().describe("Channel source"),
|
|
3394
|
+
identifier: z18.string().optional().describe("User identifier"),
|
|
3395
|
+
metadata: z18.record(z18.string(), z18.any()).optional().describe("Additional metadata")
|
|
3396
|
+
});
|
|
3397
|
+
var ChatLogNode = {
|
|
3398
|
+
label: "Chat Log",
|
|
3399
|
+
type: "ChatLogNode",
|
|
3400
|
+
category: "chat",
|
|
3401
|
+
description: "Saves a message to the chat history. Supports inbound (user) and outbound (assistant) messages.",
|
|
3402
|
+
icon: "\u{1F4AC}",
|
|
3403
|
+
group: "Chat",
|
|
3404
|
+
tags: {
|
|
3405
|
+
execution: "async",
|
|
3406
|
+
group: "Chat"
|
|
3407
|
+
},
|
|
3408
|
+
fields: [
|
|
3409
|
+
{
|
|
3410
|
+
id: "threadId",
|
|
3411
|
+
label: "Thread ID",
|
|
3412
|
+
type: "string",
|
|
3413
|
+
required: true,
|
|
3414
|
+
placeholder: "From GetOrCreateThread node",
|
|
3415
|
+
handle: {
|
|
3416
|
+
type: "input",
|
|
3417
|
+
label: "Thread ID",
|
|
3418
|
+
name: "threadId",
|
|
3419
|
+
fieldType: "string"
|
|
3420
|
+
}
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
id: "direction",
|
|
3424
|
+
label: "Direction",
|
|
3425
|
+
type: "select",
|
|
3426
|
+
required: true,
|
|
3427
|
+
defaultValue: "inbound",
|
|
3428
|
+
options: [
|
|
3429
|
+
{ label: "Inbound (User \u2192 System)", value: "inbound" },
|
|
3430
|
+
{ label: "Outbound (System \u2192 User)", value: "outbound" }
|
|
3431
|
+
]
|
|
3432
|
+
},
|
|
3433
|
+
{
|
|
3434
|
+
id: "content",
|
|
3435
|
+
label: "Content",
|
|
3436
|
+
type: "string",
|
|
3437
|
+
required: true,
|
|
3438
|
+
placeholder: "Message content",
|
|
3439
|
+
handle: {
|
|
3440
|
+
type: "input",
|
|
3441
|
+
label: "Content",
|
|
3442
|
+
name: "content",
|
|
3443
|
+
fieldType: "string"
|
|
3444
|
+
}
|
|
3445
|
+
},
|
|
3446
|
+
{
|
|
3447
|
+
id: "source",
|
|
3448
|
+
label: "Source",
|
|
3449
|
+
type: "string",
|
|
3450
|
+
required: false,
|
|
3451
|
+
defaultValue: "whatsapp",
|
|
3452
|
+
placeholder: "whatsapp, telegram, web",
|
|
3453
|
+
handle: {
|
|
3454
|
+
type: "input",
|
|
3455
|
+
label: "Source",
|
|
3456
|
+
name: "source",
|
|
3457
|
+
fieldType: "string"
|
|
3458
|
+
}
|
|
3459
|
+
},
|
|
3460
|
+
{
|
|
3461
|
+
id: "identifier",
|
|
3462
|
+
label: "Identifier",
|
|
3463
|
+
type: "string",
|
|
3464
|
+
required: false,
|
|
3465
|
+
placeholder: "+5511999999999",
|
|
3466
|
+
handle: {
|
|
3467
|
+
type: "input",
|
|
3468
|
+
label: "Identifier",
|
|
3469
|
+
name: "identifier",
|
|
3470
|
+
fieldType: "string"
|
|
3471
|
+
}
|
|
3472
|
+
},
|
|
3473
|
+
{
|
|
3474
|
+
id: "messageId",
|
|
3475
|
+
label: "Message ID",
|
|
3476
|
+
type: "string",
|
|
3477
|
+
required: true,
|
|
3478
|
+
typeable: false,
|
|
3479
|
+
handle: {
|
|
3480
|
+
type: "output",
|
|
3481
|
+
label: "Message ID",
|
|
3482
|
+
name: "messageId",
|
|
3483
|
+
fieldType: "string"
|
|
3484
|
+
}
|
|
3485
|
+
},
|
|
3486
|
+
{
|
|
3487
|
+
id: "success",
|
|
3488
|
+
label: "Success",
|
|
3489
|
+
type: "boolean",
|
|
3490
|
+
required: true,
|
|
3491
|
+
typeable: false,
|
|
3492
|
+
handle: {
|
|
3493
|
+
type: "output",
|
|
3494
|
+
label: "Success",
|
|
3495
|
+
name: "success",
|
|
3496
|
+
fieldType: "boolean"
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
]
|
|
3500
|
+
};
|
|
3501
|
+
|
|
3502
|
+
// src/nodes/chat/chatLog/function.ts
|
|
3503
|
+
var ChatLogNodeFunction = async (inputs) => {
|
|
3504
|
+
const fieldValues = inputs.fieldValues || {};
|
|
3505
|
+
const context = inputs.context || {};
|
|
3506
|
+
const threadId = fieldValues.threadId;
|
|
3507
|
+
const direction = fieldValues.direction;
|
|
3508
|
+
const content = fieldValues.content;
|
|
3509
|
+
const source = fieldValues.source;
|
|
3510
|
+
const identifier = fieldValues.identifier;
|
|
3511
|
+
const companyId = context?.companyId;
|
|
3512
|
+
if (!companyId) {
|
|
3513
|
+
throw new Error("ChatLog requires companyId in context for tenant isolation");
|
|
3514
|
+
}
|
|
3515
|
+
if (!threadId || !content) {
|
|
3516
|
+
throw new Error("ChatLog requires threadId and content");
|
|
3517
|
+
}
|
|
3518
|
+
const role = direction === "inbound" ? "user" : "assistant";
|
|
3519
|
+
const db = context?.db;
|
|
3520
|
+
if (!db) {
|
|
3521
|
+
throw new Error("ChatLog requires database connection in context");
|
|
3522
|
+
}
|
|
3523
|
+
try {
|
|
3524
|
+
const sessionResult = await db.query(`
|
|
3525
|
+
SELECT id FROM chat_sessions
|
|
3526
|
+
WHERE session_id = $1 AND company_id = $2
|
|
3527
|
+
LIMIT 1
|
|
3528
|
+
`, [threadId, companyId]);
|
|
3529
|
+
if (!sessionResult.rows || sessionResult.rows.length === 0) {
|
|
3530
|
+
throw new Error(`Session not found for threadId: ${threadId}`);
|
|
3531
|
+
}
|
|
3532
|
+
const sessionId = sessionResult.rows[0].id;
|
|
3533
|
+
const messageId = crypto.randomUUID();
|
|
3534
|
+
await db.query(`
|
|
3535
|
+
INSERT INTO chat_messages (id, session_id, role, content, metadata)
|
|
3536
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
3537
|
+
`, [
|
|
3538
|
+
messageId,
|
|
3539
|
+
sessionId,
|
|
3540
|
+
role,
|
|
3541
|
+
content,
|
|
3542
|
+
JSON.stringify({
|
|
3543
|
+
direction,
|
|
3544
|
+
source: source || null,
|
|
3545
|
+
identifier: identifier || null
|
|
3546
|
+
})
|
|
3547
|
+
]);
|
|
3548
|
+
await db.query(`
|
|
3549
|
+
UPDATE chat_sessions
|
|
3550
|
+
SET updated_at = NOW()
|
|
3551
|
+
WHERE id = $1 AND company_id = $2
|
|
3552
|
+
`, [sessionId, companyId]);
|
|
3553
|
+
return {
|
|
3554
|
+
messageId,
|
|
3555
|
+
success: true
|
|
3556
|
+
};
|
|
3557
|
+
} catch (error) {
|
|
3558
|
+
console.error("[ChatLog] Error:", error);
|
|
3559
|
+
return {
|
|
3560
|
+
messageId: null,
|
|
3561
|
+
success: false
|
|
3562
|
+
};
|
|
3563
|
+
}
|
|
3564
|
+
};
|
|
3565
|
+
|
|
3220
3566
|
// src/nodes/consts/nodes.ts
|
|
3221
3567
|
var nodes = [
|
|
3222
3568
|
ChatInputNode,
|
|
@@ -3243,7 +3589,9 @@ var nodes = [
|
|
|
3243
3589
|
PromptGuardrailNode,
|
|
3244
3590
|
RuleGuardrailNode,
|
|
3245
3591
|
FunctionGuardrailNode,
|
|
3246
|
-
ModelGuardrailNode
|
|
3592
|
+
ModelGuardrailNode,
|
|
3593
|
+
GetOrCreateThreadNode,
|
|
3594
|
+
ChatLogNode
|
|
3247
3595
|
];
|
|
3248
3596
|
var nodes_default = nodes;
|
|
3249
3597
|
|
|
@@ -3365,7 +3713,9 @@ var nodeFunctions = {
|
|
|
3365
3713
|
PromptGuardrailNode: PromptGuardrailNodeFunction,
|
|
3366
3714
|
RuleGuardrailNode: RuleGuardrailNodeFunction,
|
|
3367
3715
|
FunctionGuardrailNode: FunctionGuardrailNodeFunction,
|
|
3368
|
-
ModelGuardrailNode: ModelGuardrailNodeFunction
|
|
3716
|
+
ModelGuardrailNode: ModelGuardrailNodeFunction,
|
|
3717
|
+
GetOrCreateThreadNode: GetOrCreateThreadNodeFunction,
|
|
3718
|
+
ChatLogNode: ChatLogNodeFunction
|
|
3369
3719
|
};
|
|
3370
3720
|
var node_functions_default = nodeFunctions;
|
|
3371
3721
|
|
|
@@ -3479,12 +3829,12 @@ var HttpPutInputNodeFunction = (params) => {
|
|
|
3479
3829
|
};
|
|
3480
3830
|
|
|
3481
3831
|
// src/nodes/inputs/http/put/schema.ts
|
|
3482
|
-
import { z as
|
|
3483
|
-
var HttpPutInputNodeSchema =
|
|
3832
|
+
import { z as z19 } from "zod";
|
|
3833
|
+
var HttpPutInputNodeSchema = z19.object({
|
|
3484
3834
|
route: RouteSchema,
|
|
3485
|
-
queryParams:
|
|
3486
|
-
headers:
|
|
3487
|
-
body:
|
|
3835
|
+
queryParams: z19.array(QueryParamSchema).optional().describe("Query parameters configuration"),
|
|
3836
|
+
headers: z19.array(HeaderSchema).optional().describe("Headers configuration"),
|
|
3837
|
+
body: z19.array(BodyFieldSchema).optional().describe("Body fields configuration")
|
|
3488
3838
|
});
|
|
3489
3839
|
|
|
3490
3840
|
// src/nodes/inputs/http/delete/data.ts
|
|
@@ -3576,11 +3926,11 @@ var HttpDeleteInputNodeFunction = async (params) => {
|
|
|
3576
3926
|
};
|
|
3577
3927
|
|
|
3578
3928
|
// src/nodes/inputs/http/delete/schema.ts
|
|
3579
|
-
import { z as
|
|
3580
|
-
var HttpDeleteInputNodeSchema =
|
|
3929
|
+
import { z as z20 } from "zod";
|
|
3930
|
+
var HttpDeleteInputNodeSchema = z20.object({
|
|
3581
3931
|
route: RouteSchema,
|
|
3582
|
-
queryParams:
|
|
3583
|
-
headers:
|
|
3932
|
+
queryParams: z20.array(QueryParamSchema).optional().describe("Query parameters configuration"),
|
|
3933
|
+
headers: z20.array(HeaderSchema).optional().describe("Headers configuration")
|
|
3584
3934
|
});
|
|
3585
3935
|
|
|
3586
3936
|
// src/nodes/inputs/http/patch/data.ts
|
|
@@ -3693,12 +4043,12 @@ var HttpPatchInputNodeFunction = (params) => {
|
|
|
3693
4043
|
};
|
|
3694
4044
|
|
|
3695
4045
|
// src/nodes/inputs/http/patch/schema.ts
|
|
3696
|
-
import { z as
|
|
3697
|
-
var HttpPatchInputNodeSchema =
|
|
4046
|
+
import { z as z21 } from "zod";
|
|
4047
|
+
var HttpPatchInputNodeSchema = z21.object({
|
|
3698
4048
|
route: RouteSchema,
|
|
3699
|
-
queryParams:
|
|
3700
|
-
headers:
|
|
3701
|
-
body:
|
|
4049
|
+
queryParams: z21.array(QueryParamSchema).optional().describe("Query parameters configuration"),
|
|
4050
|
+
headers: z21.array(HeaderSchema).optional().describe("Headers configuration"),
|
|
4051
|
+
body: z21.array(BodyFieldSchema).optional().describe("Body fields configuration")
|
|
3702
4052
|
});
|
|
3703
4053
|
|
|
3704
4054
|
// src/nodes/inputs/http/utils.ts
|
|
@@ -3757,7 +4107,13 @@ export {
|
|
|
3757
4107
|
AiToolNodeFunction,
|
|
3758
4108
|
AiToolNodeSchema,
|
|
3759
4109
|
BodyFieldSchema,
|
|
4110
|
+
ChatLogNode,
|
|
4111
|
+
ChatLogNodeFunction,
|
|
4112
|
+
ChatLogSchema,
|
|
3760
4113
|
CustomToolSchema,
|
|
4114
|
+
GetOrCreateThreadNode,
|
|
4115
|
+
GetOrCreateThreadNodeFunction,
|
|
4116
|
+
GetOrCreateThreadSchema,
|
|
3761
4117
|
HTTP_METHODS,
|
|
3762
4118
|
HTTP_NODE_TYPES,
|
|
3763
4119
|
HeaderSchema,
|