@atomoz/workflows-nodes 0.1.27 → 0.1.29

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.js CHANGED
@@ -243,7 +243,11 @@ var ChatInputNodeFunction = (params) => {
243
243
  const { message: configMessage, chatId: configChatId } = fieldValues || {};
244
244
  const actualData = {
245
245
  message: request?.message ?? configMessage ?? "",
246
- chatId: request?.chatId ?? configChatId ?? null
246
+ chatId: request?.chatId ?? configChatId ?? null,
247
+ roomId: request?.sessionId ?? request?.chatId ?? configChatId ?? null,
248
+ // Room = Session/Chat
249
+ source: "chat"
250
+ // Hardcoded source for web chat
247
251
  };
248
252
  if (!actualData.message || typeof actualData.message !== "string") {
249
253
  throw new Error("Message is required for ChatInputNode");
@@ -286,6 +290,33 @@ var ChatInputNode = {
286
290
  name: "chatId",
287
291
  fieldType: "string"
288
292
  }
293
+ },
294
+ {
295
+ id: "roomId",
296
+ label: "Room ID",
297
+ type: "string",
298
+ required: false,
299
+ typeable: false,
300
+ handle: {
301
+ type: "output",
302
+ label: "Room ID",
303
+ name: "roomId",
304
+ fieldType: "string"
305
+ }
306
+ },
307
+ {
308
+ id: "source",
309
+ label: "Source",
310
+ type: "string",
311
+ required: false,
312
+ typeable: false,
313
+ defaultValue: "chat",
314
+ handle: {
315
+ type: "output",
316
+ label: "Source",
317
+ name: "source",
318
+ fieldType: "string"
319
+ }
289
320
  }
290
321
  ]
291
322
  };
@@ -1008,7 +1039,7 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
1008
1039
  case "gemini":
1009
1040
  return new ChatGoogle({
1010
1041
  model: "gemini-flash-latest",
1011
- apiKey: "AIzaSyAWj0Al2sVJ8vqaRN4UY7c6imAg7a3NbEc",
1042
+ apiKey: "AIzaSyBLeXr43XWg1lOQfsUTZQ85IX-IYYpZIW0",
1012
1043
  streaming
1013
1044
  });
1014
1045
  case "openai":
@@ -1034,6 +1065,18 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
1034
1065
  }
1035
1066
 
1036
1067
  // src/utils/guardrail-executor.ts
1068
+ function emitGuardrailEvent(context, name, passed, action, details) {
1069
+ if (context?.emitter?.emitThought) {
1070
+ context.emitter.emitThought({
1071
+ content: `guardrail:${passed ? "passed" : "failed"}:${name}`,
1072
+ type: "guardrail",
1073
+ name,
1074
+ passed,
1075
+ action: action || "evaluate",
1076
+ details
1077
+ });
1078
+ }
1079
+ }
1037
1080
  async function loadChatHistory(context) {
1038
1081
  const checkpointer = context?.checkpointer;
1039
1082
  const sessionId = context?.sessionId;
@@ -1128,6 +1171,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first", conte
1128
1171
  if (!guardPassed && actionInstruction) {
1129
1172
  violationMessage = actionInstruction;
1130
1173
  }
1174
+ emitGuardrailEvent(context, guard.name, guardPassed, guard.action, violationMessage || "Rule passed");
1131
1175
  } else if (guard.type === "function") {
1132
1176
  const { nodeFunction, name, actionInstruction } = guard;
1133
1177
  if (typeof nodeFunction === "function") {
@@ -1160,6 +1204,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first", conte
1160
1204
  guardPassed = false;
1161
1205
  violationMessage = `Erro na fun\xE7\xE3o guardrail: ${error instanceof Error ? error.message : String(error)}`;
1162
1206
  }
1207
+ emitGuardrailEvent(context, name, guardPassed, guard.action, violationMessage || "Function passed");
1163
1208
  }
1164
1209
  } else if (guard.type === "model") {
1165
1210
  const { model, evaluationPrompt, name, actionInstruction } = guard;
@@ -1227,6 +1272,7 @@ Reescreva o conte\xFAdo corrigindo a viola\xE7\xE3o. Retorne APENAS o texto corr
1227
1272
  message: violationMessage,
1228
1273
  action: "fix"
1229
1274
  });
1275
+ emitGuardrailEvent(context, name, false, "fix", `Content fixed: ${fixedContent.slice(0, 100)}...`);
1230
1276
  } catch (fixError) {
1231
1277
  console.error(`[GUARDRAIL LLM] Erro ao corrigir conte\xFAdo:`, fixError);
1232
1278
  }
@@ -1238,8 +1284,10 @@ Reescreva o conte\xFAdo corrigindo a viola\xE7\xE3o. Retorne APENAS o texto corr
1238
1284
  guardPassed = false;
1239
1285
  violationMessage = actionInstruction || `Modelo de avalia\xE7\xE3o "${name}" detectou viola\xE7\xE3o de seguran\xE7a/pol\xEDtica.`;
1240
1286
  console.log(`[GUARDRAIL LLM] Resultado: UNSAFE - Bloqueado`);
1287
+ emitGuardrailEvent(context, name, false, guard.action, violationMessage);
1241
1288
  } else {
1242
1289
  console.log(`[GUARDRAIL LLM] Resultado: SAFE - Aprovado`);
1290
+ emitGuardrailEvent(context, name, true, "approve", "Content passed evaluation");
1243
1291
  }
1244
1292
  }
1245
1293
  } catch (error) {
@@ -1944,7 +1992,8 @@ import { tool } from "@langchain/core/tools";
1944
1992
  // src/nodes/memory/postgres/data.ts
1945
1993
  import { z as z8 } from "zod";
1946
1994
  var PostgresMemoryNodeSchema = z8.object({
1947
- connectionString: z8.string().describe("PostgreSQL connection string")
1995
+ connectionString: z8.string().describe("PostgreSQL connection string"),
1996
+ threadId: z8.string().optional().describe("Thread ID for conversation isolation")
1948
1997
  });
1949
1998
  var PostgresMemoryNode = {
1950
1999
  label: "Postgres Memory",
@@ -1966,6 +2015,20 @@ var PostgresMemoryNode = {
1966
2015
  defaultValue: "postgresql://yugabyte:yugabyte@localhost:5433/workflows",
1967
2016
  placeholder: "postgresql://user:pass@host:5432/database"
1968
2017
  },
2018
+ {
2019
+ id: "threadId",
2020
+ label: "Thread ID",
2021
+ type: "string",
2022
+ required: false,
2023
+ typeable: true,
2024
+ placeholder: "Thread/Session ID for conversation isolation",
2025
+ handle: {
2026
+ type: "input",
2027
+ label: "Thread ID",
2028
+ name: "threadId",
2029
+ fieldType: "string"
2030
+ }
2031
+ },
1969
2032
  {
1970
2033
  id: "checkpointer",
1971
2034
  label: "Checkpointer",
@@ -1988,12 +2051,15 @@ var PostgresMemoryNodeFunction = async (inputs) => {
1988
2051
  const { $field: _$field, $req: _$req, $inputs: _$inputs, $vars: _$vars } = inputs;
1989
2052
  const fieldValues = inputs.fieldValues || {};
1990
2053
  const connectionString = fieldValues.connectionString || inputs.connectionString || "postgresql://yugabyte:yugabyte@localhost:5433/workflows";
2054
+ const threadId = inputs.threadId ?? fieldValues.threadId;
1991
2055
  try {
1992
2056
  const checkpointer = PostgresSaver.fromConnString(connectionString);
1993
2057
  await checkpointer.setup();
1994
- console.log("\u2705 PostgresMemory: Checkpointer initialized");
2058
+ console.log(`\u2705 PostgresMemory: Checkpointer initialized${threadId ? ` with threadId: ${threadId}` : ""}`);
1995
2059
  return {
1996
2060
  checkpointer,
2061
+ threadId,
2062
+ // Pass threadId to agent for conversation isolation
1997
2063
  type: "PostgresMemoryNode",
1998
2064
  connectionString: connectionString.replace(/:[^:@]+@/, ":***@")
1999
2065
  // Hide password in output
@@ -2397,6 +2463,20 @@ var WhatsappMessageTriggerNode = {
2397
2463
  name: "message",
2398
2464
  fieldType: "string"
2399
2465
  }
2466
+ },
2467
+ {
2468
+ id: "source",
2469
+ label: "Source",
2470
+ type: "string",
2471
+ required: false,
2472
+ typeable: false,
2473
+ defaultValue: "whatsapp",
2474
+ handle: {
2475
+ type: "output",
2476
+ label: "Source",
2477
+ name: "source",
2478
+ fieldType: "string"
2479
+ }
2400
2480
  }
2401
2481
  ]
2402
2482
  };
@@ -3217,6 +3297,595 @@ var ModelGuardrailNodeFunction = async (inputs) => {
3217
3297
  };
3218
3298
  };
3219
3299
 
3300
+ // src/nodes/chat/getOrCreateThread/data.ts
3301
+ import { z as z17 } from "zod";
3302
+ var GetOrCreateThreadSchema = z17.object({
3303
+ source: z17.string().describe("Channel source: whatsapp, telegram, web, etc."),
3304
+ identifier: z17.string().describe("User identifier: phone number, chat_id, userId"),
3305
+ timeoutMinutes: z17.number().optional().describe("Inactivity timeout in minutes (default: 1440 = 24h)")
3306
+ });
3307
+ var GetOrCreateThreadNode = {
3308
+ label: "Get or Create Thread",
3309
+ type: "GetOrCreateThreadNode",
3310
+ category: "chat",
3311
+ description: "Generates or retrieves a threadId based on identifier + timeout. Ensures tenant isolation.",
3312
+ icon: "\u{1F9F5}",
3313
+ group: "Chat",
3314
+ tags: {
3315
+ execution: "async",
3316
+ group: "Chat"
3317
+ },
3318
+ fields: [
3319
+ {
3320
+ id: "source",
3321
+ label: "Source",
3322
+ type: "string",
3323
+ required: true,
3324
+ defaultValue: "whatsapp",
3325
+ placeholder: "whatsapp, telegram, web",
3326
+ handle: {
3327
+ type: "input",
3328
+ label: "Source",
3329
+ name: "source",
3330
+ fieldType: "string"
3331
+ }
3332
+ },
3333
+ {
3334
+ id: "identifier",
3335
+ label: "Identifier",
3336
+ type: "string",
3337
+ required: true,
3338
+ placeholder: "+5511999999999",
3339
+ handle: {
3340
+ type: "input",
3341
+ label: "Identifier",
3342
+ name: "identifier",
3343
+ fieldType: "string"
3344
+ }
3345
+ },
3346
+ {
3347
+ id: "timeoutMinutes",
3348
+ label: "Timeout (minutes)",
3349
+ type: "number",
3350
+ required: false,
3351
+ defaultValue: "1440",
3352
+ placeholder: "1440 (24 hours)"
3353
+ },
3354
+ {
3355
+ id: "threadId",
3356
+ label: "Thread ID",
3357
+ type: "string",
3358
+ required: true,
3359
+ typeable: false,
3360
+ handle: {
3361
+ type: "output",
3362
+ label: "Thread ID",
3363
+ name: "threadId",
3364
+ fieldType: "string"
3365
+ }
3366
+ },
3367
+ {
3368
+ id: "isNew",
3369
+ label: "Is New Thread",
3370
+ type: "boolean",
3371
+ required: true,
3372
+ typeable: false,
3373
+ handle: {
3374
+ type: "output",
3375
+ label: "Is New",
3376
+ name: "isNew",
3377
+ fieldType: "boolean"
3378
+ }
3379
+ }
3380
+ ]
3381
+ };
3382
+
3383
+ // src/nodes/chat/getOrCreateThread/function.ts
3384
+ var GetOrCreateThreadNodeFunction = async (inputs) => {
3385
+ const fieldValues = inputs.fieldValues || {};
3386
+ const context = inputs.context || {};
3387
+ const source = fieldValues.source;
3388
+ const identifier = fieldValues.identifier;
3389
+ const timeoutMinutes = Number(fieldValues.timeoutMinutes) || 1440;
3390
+ const companyId = context?.companyId;
3391
+ if (!companyId) {
3392
+ throw new Error("GetOrCreateThread requires companyId in context for tenant isolation");
3393
+ }
3394
+ if (!source || !identifier) {
3395
+ throw new Error("GetOrCreateThread requires source and identifier");
3396
+ }
3397
+ const timeoutMs = timeoutMinutes * 60 * 1e3;
3398
+ const thresholdDate = new Date(Date.now() - timeoutMs);
3399
+ const db = context?.db;
3400
+ if (!db) {
3401
+ throw new Error("GetOrCreateThread requires database connection in context");
3402
+ }
3403
+ try {
3404
+ const existingSessions = await db.query(`
3405
+ SELECT id, session_id, updated_at
3406
+ FROM chat_sessions
3407
+ WHERE company_id = $1
3408
+ AND metadata->>'source' = $2
3409
+ AND metadata->>'identifier' = $3
3410
+ AND updated_at > $4
3411
+ ORDER BY updated_at DESC
3412
+ LIMIT 1
3413
+ `, [companyId, source, identifier, thresholdDate]);
3414
+ if (existingSessions.rows && existingSessions.rows.length > 0) {
3415
+ const session = existingSessions.rows[0];
3416
+ await db.query(`
3417
+ UPDATE chat_sessions
3418
+ SET updated_at = NOW()
3419
+ WHERE id = $1 AND company_id = $2
3420
+ `, [session.id, companyId]);
3421
+ return {
3422
+ threadId: session.session_id,
3423
+ isNew: false
3424
+ };
3425
+ }
3426
+ const newSessionId = crypto.randomUUID();
3427
+ const workflowId = context?.workflowId;
3428
+ await db.query(`
3429
+ INSERT INTO chat_sessions (workflow_id, company_id, chat_id, session_id, metadata)
3430
+ VALUES ($1, $2, $3, $4, $5)
3431
+ `, [
3432
+ workflowId || companyId,
3433
+ // fallback to companyId if no workflowId
3434
+ companyId,
3435
+ `${source}:${identifier}`,
3436
+ // chatId as composite key
3437
+ newSessionId,
3438
+ JSON.stringify({ source, identifier })
3439
+ ]);
3440
+ return {
3441
+ threadId: newSessionId,
3442
+ isNew: true
3443
+ };
3444
+ } catch (error) {
3445
+ console.error("[GetOrCreateThread] Error:", error);
3446
+ throw error;
3447
+ }
3448
+ };
3449
+
3450
+ // src/nodes/chat/chatLog/data.ts
3451
+ import { z as z18 } from "zod";
3452
+ var ChatLogSchema = z18.object({
3453
+ threadId: z18.string().describe("Thread ID from GetOrCreateThread"),
3454
+ direction: z18.enum(["inbound", "outbound"]).describe("Message direction"),
3455
+ content: z18.string().describe("Message content"),
3456
+ source: z18.string().optional().describe("Channel source"),
3457
+ identifier: z18.string().optional().describe("User identifier"),
3458
+ metadata: z18.record(z18.string(), z18.any()).optional().describe("Additional metadata")
3459
+ });
3460
+ var ChatLogNode = {
3461
+ label: "Chat Log",
3462
+ type: "ChatLogNode",
3463
+ category: "chat",
3464
+ description: "Saves a message to the chat history. Supports inbound (user) and outbound (assistant) messages.",
3465
+ icon: "\u{1F4AC}",
3466
+ group: "Chat",
3467
+ tags: {
3468
+ execution: "async",
3469
+ group: "Chat"
3470
+ },
3471
+ fields: [
3472
+ {
3473
+ id: "threadId",
3474
+ label: "Thread ID",
3475
+ type: "string",
3476
+ required: true,
3477
+ placeholder: "From GetOrCreateThread node",
3478
+ handle: {
3479
+ type: "input",
3480
+ label: "Thread ID",
3481
+ name: "threadId",
3482
+ fieldType: "string"
3483
+ }
3484
+ },
3485
+ {
3486
+ id: "direction",
3487
+ label: "Direction",
3488
+ type: "select",
3489
+ required: true,
3490
+ defaultValue: "inbound",
3491
+ options: [
3492
+ { label: "Inbound (User \u2192 System)", value: "inbound" },
3493
+ { label: "Outbound (System \u2192 User)", value: "outbound" }
3494
+ ]
3495
+ },
3496
+ {
3497
+ id: "content",
3498
+ label: "Content",
3499
+ type: "string",
3500
+ required: true,
3501
+ placeholder: "Message content",
3502
+ handle: {
3503
+ type: "input",
3504
+ label: "Content",
3505
+ name: "content",
3506
+ fieldType: "string"
3507
+ }
3508
+ },
3509
+ {
3510
+ id: "source",
3511
+ label: "Source",
3512
+ type: "string",
3513
+ required: false,
3514
+ defaultValue: "whatsapp",
3515
+ placeholder: "whatsapp, telegram, web",
3516
+ handle: {
3517
+ type: "input",
3518
+ label: "Source",
3519
+ name: "source",
3520
+ fieldType: "string"
3521
+ }
3522
+ },
3523
+ {
3524
+ id: "identifier",
3525
+ label: "Identifier",
3526
+ type: "string",
3527
+ required: false,
3528
+ placeholder: "+5511999999999",
3529
+ handle: {
3530
+ type: "input",
3531
+ label: "Identifier",
3532
+ name: "identifier",
3533
+ fieldType: "string"
3534
+ }
3535
+ },
3536
+ {
3537
+ id: "messageId",
3538
+ label: "Message ID",
3539
+ type: "string",
3540
+ required: true,
3541
+ typeable: false,
3542
+ handle: {
3543
+ type: "output",
3544
+ label: "Message ID",
3545
+ name: "messageId",
3546
+ fieldType: "string"
3547
+ }
3548
+ },
3549
+ {
3550
+ id: "success",
3551
+ label: "Success",
3552
+ type: "boolean",
3553
+ required: true,
3554
+ typeable: false,
3555
+ handle: {
3556
+ type: "output",
3557
+ label: "Success",
3558
+ name: "success",
3559
+ fieldType: "boolean"
3560
+ }
3561
+ }
3562
+ ]
3563
+ };
3564
+
3565
+ // src/nodes/chat/chatLog/function.ts
3566
+ var ChatLogNodeFunction = async (inputs) => {
3567
+ const fieldValues = inputs.fieldValues || {};
3568
+ const context = inputs.context || {};
3569
+ const threadId = fieldValues.threadId;
3570
+ const direction = fieldValues.direction;
3571
+ const content = fieldValues.content;
3572
+ const source = fieldValues.source;
3573
+ const identifier = fieldValues.identifier;
3574
+ const companyId = context?.companyId;
3575
+ if (!companyId) {
3576
+ throw new Error("ChatLog requires companyId in context for tenant isolation");
3577
+ }
3578
+ if (!threadId || !content) {
3579
+ throw new Error("ChatLog requires threadId and content");
3580
+ }
3581
+ const role = direction === "inbound" ? "user" : "assistant";
3582
+ const db = context?.db;
3583
+ if (!db) {
3584
+ throw new Error("ChatLog requires database connection in context");
3585
+ }
3586
+ try {
3587
+ const sessionResult = await db.query(`
3588
+ SELECT id FROM chat_sessions
3589
+ WHERE session_id = $1 AND company_id = $2
3590
+ LIMIT 1
3591
+ `, [threadId, companyId]);
3592
+ if (!sessionResult.rows || sessionResult.rows.length === 0) {
3593
+ throw new Error(`Session not found for threadId: ${threadId}`);
3594
+ }
3595
+ const sessionId = sessionResult.rows[0].id;
3596
+ const messageId = crypto.randomUUID();
3597
+ await db.query(`
3598
+ INSERT INTO chat_messages (id, session_id, role, content, metadata)
3599
+ VALUES ($1, $2, $3, $4, $5)
3600
+ `, [
3601
+ messageId,
3602
+ sessionId,
3603
+ role,
3604
+ content,
3605
+ JSON.stringify({
3606
+ direction,
3607
+ source: source || null,
3608
+ identifier: identifier || null
3609
+ })
3610
+ ]);
3611
+ await db.query(`
3612
+ UPDATE chat_sessions
3613
+ SET updated_at = NOW()
3614
+ WHERE id = $1 AND company_id = $2
3615
+ `, [sessionId, companyId]);
3616
+ return {
3617
+ messageId,
3618
+ success: true
3619
+ };
3620
+ } catch (error) {
3621
+ console.error("[ChatLog] Error:", error);
3622
+ return {
3623
+ messageId: null,
3624
+ success: false
3625
+ };
3626
+ }
3627
+ };
3628
+
3629
+ // src/nodes/chat/isHumanActive/data.ts
3630
+ var IsHumanActiveData = {
3631
+ label: "Is Human Active?",
3632
+ type: "isHumanActive",
3633
+ category: "chat",
3634
+ description: "Checks if a human agent is currently handling the conversation (handoff mode).",
3635
+ icon: "\u{1F464}",
3636
+ group: "Chat",
3637
+ tags: {
3638
+ execution: "async",
3639
+ group: "Chat"
3640
+ },
3641
+ fields: [
3642
+ {
3643
+ id: "threadId",
3644
+ label: "Thread ID",
3645
+ type: "string",
3646
+ required: false,
3647
+ typeable: true,
3648
+ placeholder: "Session/Thread ID (optional, uses context if empty)",
3649
+ handle: {
3650
+ type: "input",
3651
+ label: "Thread ID",
3652
+ name: "threadId",
3653
+ fieldType: "string"
3654
+ }
3655
+ },
3656
+ {
3657
+ id: "active",
3658
+ label: "Active",
3659
+ type: "boolean",
3660
+ required: true,
3661
+ typeable: false,
3662
+ handle: {
3663
+ type: "output",
3664
+ label: "Active",
3665
+ name: "active",
3666
+ fieldType: "continue"
3667
+ }
3668
+ },
3669
+ {
3670
+ id: "inactive",
3671
+ label: "Inactive",
3672
+ type: "boolean",
3673
+ required: true,
3674
+ typeable: false,
3675
+ handle: {
3676
+ type: "output",
3677
+ label: "Inactive",
3678
+ name: "inactive",
3679
+ fieldType: "continue"
3680
+ }
3681
+ }
3682
+ ]
3683
+ };
3684
+
3685
+ // src/nodes/chat/isHumanActive/function.ts
3686
+ var isHumanActiveFunc = async (inputs) => {
3687
+ const fieldValues = inputs.fieldValues || {};
3688
+ const context = inputs.context || {};
3689
+ const sessionId = inputs.threadId || fieldValues.threadId || context?.sessionId || context?.chatId;
3690
+ if (!sessionId) {
3691
+ console.warn("[IsHumanActive] No sessionId found in input or context.");
3692
+ return {
3693
+ active: false,
3694
+ inactive: true
3695
+ };
3696
+ }
3697
+ const db = context?.db;
3698
+ if (!db) {
3699
+ console.warn("[IsHumanActive] No database connection in context.");
3700
+ return { active: false, inactive: true };
3701
+ }
3702
+ try {
3703
+ const result = await db.query(`
3704
+ SELECT human_active_until
3705
+ FROM chat_sessions
3706
+ WHERE session_id = $1
3707
+ LIMIT 1
3708
+ `, [sessionId]);
3709
+ const session = result.rows?.[0];
3710
+ if (!session) {
3711
+ console.warn(`[IsHumanActive] Session not found: ${sessionId}`);
3712
+ return { active: false, inactive: true };
3713
+ }
3714
+ const now = /* @__PURE__ */ new Date();
3715
+ const isActive = session.human_active_until && new Date(session.human_active_until) > now;
3716
+ console.log(`[IsHumanActive] Session: ${sessionId}, Until: ${session.human_active_until}, Active: ${isActive}`);
3717
+ return {
3718
+ active: !!isActive,
3719
+ inactive: !isActive
3720
+ };
3721
+ } catch (error) {
3722
+ console.error("[IsHumanActive] Error querying session:", error);
3723
+ return { active: false, inactive: true };
3724
+ }
3725
+ };
3726
+
3727
+ // src/nodes/logic/varNode/data.ts
3728
+ var VarNode = {
3729
+ label: "Variable",
3730
+ type: "VarNode",
3731
+ category: "logic",
3732
+ description: "Stores a value from multiple inputs. Strategy: keep first or last value received.",
3733
+ icon: "\u{1F4E6}",
3734
+ group: "Control",
3735
+ tags: {
3736
+ execution: "sync",
3737
+ group: "Control"
3738
+ },
3739
+ fields: [
3740
+ {
3741
+ id: "strategy",
3742
+ label: "Strategy",
3743
+ type: "select",
3744
+ required: true,
3745
+ defaultValue: "first",
3746
+ options: [
3747
+ { label: "First Value", value: "first" },
3748
+ { label: "Last Value", value: "last" }
3749
+ ]
3750
+ },
3751
+ {
3752
+ id: "value",
3753
+ label: "Value",
3754
+ type: "any",
3755
+ required: false,
3756
+ typeable: true,
3757
+ handle: {
3758
+ type: "input",
3759
+ label: "Value",
3760
+ name: "value",
3761
+ fieldType: "any",
3762
+ maxConnections: 10
3763
+ // Allow multiple connections
3764
+ }
3765
+ },
3766
+ {
3767
+ id: "output",
3768
+ label: "Output",
3769
+ type: "any",
3770
+ required: true,
3771
+ typeable: false,
3772
+ handle: {
3773
+ type: "output",
3774
+ label: "Value",
3775
+ name: "output",
3776
+ fieldType: "any"
3777
+ }
3778
+ },
3779
+ // Continue handle (hidden by default)
3780
+ {
3781
+ id: "continue",
3782
+ label: "Continue",
3783
+ type: "continue",
3784
+ typeable: false,
3785
+ active: false,
3786
+ // Hidden by default
3787
+ handle: {
3788
+ type: "output",
3789
+ label: "Continue",
3790
+ name: "continue",
3791
+ fieldType: "continue"
3792
+ }
3793
+ }
3794
+ ]
3795
+ };
3796
+
3797
+ // src/nodes/logic/varNode/function.ts
3798
+ var VarNodeFunction = async (inputs) => {
3799
+ const fieldValues = inputs.fieldValues || {};
3800
+ const strategy = fieldValues.strategy || "first";
3801
+ let values = inputs.value ?? fieldValues.value;
3802
+ if (!Array.isArray(values)) {
3803
+ values = values !== void 0 ? [values] : [];
3804
+ }
3805
+ const validValues = values.filter((v) => v !== void 0 && v !== null);
3806
+ if (validValues.length === 0) {
3807
+ return { output: void 0, continue: true };
3808
+ }
3809
+ const result = strategy === "first" ? validValues[0] : validValues[validValues.length - 1];
3810
+ return {
3811
+ output: result,
3812
+ continue: true
3813
+ };
3814
+ };
3815
+
3816
+ // src/nodes/logic/switchNode/data.ts
3817
+ var SwitchNode = {
3818
+ label: "Switch",
3819
+ type: "SwitchNode",
3820
+ category: "logic",
3821
+ description: "Routes execution based on input value. Each case triggers its corresponding path.",
3822
+ icon: "\u{1F500}",
3823
+ group: "Control",
3824
+ tags: {
3825
+ execution: "sync",
3826
+ group: "Control"
3827
+ },
3828
+ fields: [
3829
+ {
3830
+ id: "value",
3831
+ label: "Value",
3832
+ type: "string",
3833
+ required: true,
3834
+ typeable: true,
3835
+ placeholder: "Value to match",
3836
+ handle: {
3837
+ type: "input",
3838
+ label: "Value",
3839
+ name: "value",
3840
+ fieldType: "string"
3841
+ }
3842
+ },
3843
+ {
3844
+ id: "cases",
3845
+ label: "Cases",
3846
+ type: "keyValue",
3847
+ required: true,
3848
+ defaultValue: [
3849
+ { key: "whatsapp", value: "WhatsApp" },
3850
+ { key: "chat", value: "Web Chat" }
3851
+ ],
3852
+ placeholder: "Add cases (key = match value, value = label)"
3853
+ },
3854
+ {
3855
+ id: "includeDefault",
3856
+ label: "Include Default Path",
3857
+ type: "boolean",
3858
+ required: false,
3859
+ defaultValue: true
3860
+ }
3861
+ // Note: Dynamic outputs are generated based on 'cases' at runtime
3862
+ // Each case.key becomes an output handle of type 'continue'
3863
+ // Plus optional 'default' output if includeDefault is true
3864
+ ]
3865
+ };
3866
+
3867
+ // src/nodes/logic/switchNode/function.ts
3868
+ var SwitchNodeFunction = async (inputs) => {
3869
+ const fieldValues = inputs.fieldValues || {};
3870
+ const inputValue = inputs.value ?? fieldValues.value;
3871
+ const cases = fieldValues.cases || [];
3872
+ const includeDefault = fieldValues.includeDefault ?? true;
3873
+ const outputs = {};
3874
+ for (const c of cases) {
3875
+ outputs[c.key] = false;
3876
+ }
3877
+ if (includeDefault) {
3878
+ outputs["default"] = false;
3879
+ }
3880
+ const matchedCase = cases.find((c) => c.key === inputValue);
3881
+ if (matchedCase) {
3882
+ outputs[matchedCase.key] = true;
3883
+ } else if (includeDefault) {
3884
+ outputs["default"] = true;
3885
+ }
3886
+ return outputs;
3887
+ };
3888
+
3220
3889
  // src/nodes/consts/nodes.ts
3221
3890
  var nodes = [
3222
3891
  ChatInputNode,
@@ -3243,7 +3912,12 @@ var nodes = [
3243
3912
  PromptGuardrailNode,
3244
3913
  RuleGuardrailNode,
3245
3914
  FunctionGuardrailNode,
3246
- ModelGuardrailNode
3915
+ ModelGuardrailNode,
3916
+ GetOrCreateThreadNode,
3917
+ ChatLogNode,
3918
+ IsHumanActiveData,
3919
+ VarNode,
3920
+ SwitchNode
3247
3921
  ];
3248
3922
  var nodes_default = nodes;
3249
3923
 
@@ -3365,7 +4039,12 @@ var nodeFunctions = {
3365
4039
  PromptGuardrailNode: PromptGuardrailNodeFunction,
3366
4040
  RuleGuardrailNode: RuleGuardrailNodeFunction,
3367
4041
  FunctionGuardrailNode: FunctionGuardrailNodeFunction,
3368
- ModelGuardrailNode: ModelGuardrailNodeFunction
4042
+ ModelGuardrailNode: ModelGuardrailNodeFunction,
4043
+ GetOrCreateThreadNode: GetOrCreateThreadNodeFunction,
4044
+ ChatLogNode: ChatLogNodeFunction,
4045
+ isHumanActive: isHumanActiveFunc,
4046
+ VarNode: VarNodeFunction,
4047
+ SwitchNode: SwitchNodeFunction
3369
4048
  };
3370
4049
  var node_functions_default = nodeFunctions;
3371
4050
 
@@ -3479,12 +4158,12 @@ var HttpPutInputNodeFunction = (params) => {
3479
4158
  };
3480
4159
 
3481
4160
  // src/nodes/inputs/http/put/schema.ts
3482
- import { z as z17 } from "zod";
3483
- var HttpPutInputNodeSchema = z17.object({
4161
+ import { z as z19 } from "zod";
4162
+ var HttpPutInputNodeSchema = z19.object({
3484
4163
  route: RouteSchema,
3485
- queryParams: z17.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3486
- headers: z17.array(HeaderSchema).optional().describe("Headers configuration"),
3487
- body: z17.array(BodyFieldSchema).optional().describe("Body fields configuration")
4164
+ queryParams: z19.array(QueryParamSchema).optional().describe("Query parameters configuration"),
4165
+ headers: z19.array(HeaderSchema).optional().describe("Headers configuration"),
4166
+ body: z19.array(BodyFieldSchema).optional().describe("Body fields configuration")
3488
4167
  });
3489
4168
 
3490
4169
  // src/nodes/inputs/http/delete/data.ts
@@ -3576,11 +4255,11 @@ var HttpDeleteInputNodeFunction = async (params) => {
3576
4255
  };
3577
4256
 
3578
4257
  // src/nodes/inputs/http/delete/schema.ts
3579
- import { z as z18 } from "zod";
3580
- var HttpDeleteInputNodeSchema = z18.object({
4258
+ import { z as z20 } from "zod";
4259
+ var HttpDeleteInputNodeSchema = z20.object({
3581
4260
  route: RouteSchema,
3582
- queryParams: z18.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3583
- headers: z18.array(HeaderSchema).optional().describe("Headers configuration")
4261
+ queryParams: z20.array(QueryParamSchema).optional().describe("Query parameters configuration"),
4262
+ headers: z20.array(HeaderSchema).optional().describe("Headers configuration")
3584
4263
  });
3585
4264
 
3586
4265
  // src/nodes/inputs/http/patch/data.ts
@@ -3693,12 +4372,12 @@ var HttpPatchInputNodeFunction = (params) => {
3693
4372
  };
3694
4373
 
3695
4374
  // src/nodes/inputs/http/patch/schema.ts
3696
- import { z as z19 } from "zod";
3697
- var HttpPatchInputNodeSchema = z19.object({
4375
+ import { z as z21 } from "zod";
4376
+ var HttpPatchInputNodeSchema = z21.object({
3698
4377
  route: RouteSchema,
3699
- queryParams: z19.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3700
- headers: z19.array(HeaderSchema).optional().describe("Headers configuration"),
3701
- body: z19.array(BodyFieldSchema).optional().describe("Body fields configuration")
4378
+ queryParams: z21.array(QueryParamSchema).optional().describe("Query parameters configuration"),
4379
+ headers: z21.array(HeaderSchema).optional().describe("Headers configuration"),
4380
+ body: z21.array(BodyFieldSchema).optional().describe("Body fields configuration")
3702
4381
  });
3703
4382
 
3704
4383
  // src/nodes/inputs/http/utils.ts
@@ -3757,7 +4436,13 @@ export {
3757
4436
  AiToolNodeFunction,
3758
4437
  AiToolNodeSchema,
3759
4438
  BodyFieldSchema,
4439
+ ChatLogNode,
4440
+ ChatLogNodeFunction,
4441
+ ChatLogSchema,
3760
4442
  CustomToolSchema,
4443
+ GetOrCreateThreadNode,
4444
+ GetOrCreateThreadNodeFunction,
4445
+ GetOrCreateThreadSchema,
3761
4446
  HTTP_METHODS,
3762
4447
  HTTP_NODE_TYPES,
3763
4448
  HeaderSchema,
@@ -3782,8 +4467,13 @@ export {
3782
4467
  IaMessageNode,
3783
4468
  IaMessageNodeFunction,
3784
4469
  IaMessageNodeSchema,
4470
+ IsHumanActiveData,
3785
4471
  QueryParamSchema,
3786
4472
  RouteSchema,
4473
+ SwitchNode,
4474
+ SwitchNodeFunction,
4475
+ VarNode,
4476
+ VarNodeFunction,
3787
4477
  WhatsappMessageTriggerNode,
3788
4478
  WhatsappSendMessageFunction,
3789
4479
  WhatsappSendMessageNode,
@@ -3803,6 +4493,7 @@ export {
3803
4493
  isHttpInputFriendlyId,
3804
4494
  isHttpInputNode,
3805
4495
  isHttpMethodNode,
4496
+ isHumanActiveFunc,
3806
4497
  node_functions_default as nodeFunctions,
3807
4498
  nodes_default as nodes,
3808
4499
  schemas