@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 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 import_zod17 = require("zod");
3573
- var HttpPutInputNodeSchema = import_zod17.z.object({
3928
+ var import_zod19 = require("zod");
3929
+ var HttpPutInputNodeSchema = import_zod19.z.object({
3574
3930
  route: RouteSchema,
3575
- queryParams: import_zod17.z.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3576
- headers: import_zod17.z.array(HeaderSchema).optional().describe("Headers configuration"),
3577
- body: import_zod17.z.array(BodyFieldSchema).optional().describe("Body fields configuration")
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 import_zod18 = require("zod");
3670
- var HttpDeleteInputNodeSchema = import_zod18.z.object({
4025
+ var import_zod20 = require("zod");
4026
+ var HttpDeleteInputNodeSchema = import_zod20.z.object({
3671
4027
  route: RouteSchema,
3672
- queryParams: import_zod18.z.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3673
- headers: import_zod18.z.array(HeaderSchema).optional().describe("Headers configuration")
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 import_zod19 = require("zod");
3787
- var HttpPatchInputNodeSchema = import_zod19.z.object({
4142
+ var import_zod21 = require("zod");
4143
+ var HttpPatchInputNodeSchema = import_zod21.z.object({
3788
4144
  route: RouteSchema,
3789
- queryParams: import_zod19.z.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3790
- headers: import_zod19.z.array(HeaderSchema).optional().describe("Headers configuration"),
3791
- body: import_zod19.z.array(BodyFieldSchema).optional().describe("Body fields configuration")
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
- export { AiSupervisorNode, AiSupervisorNodeFunction, AiSupervisorNodeSchema, AiToolNode, AiToolNodeFunction, AiToolNodeSchema, type BaseNodeType, BodyFieldSchema, CustomToolSchema, type ExecutionStep, 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 };
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
- export { AiSupervisorNode, AiSupervisorNodeFunction, AiSupervisorNodeSchema, AiToolNode, AiToolNodeFunction, AiToolNodeSchema, type BaseNodeType, BodyFieldSchema, CustomToolSchema, type ExecutionStep, 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 };
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 z17 } from "zod";
3483
- var HttpPutInputNodeSchema = z17.object({
3832
+ import { z as z19 } from "zod";
3833
+ var HttpPutInputNodeSchema = z19.object({
3484
3834
  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")
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 z18 } from "zod";
3580
- var HttpDeleteInputNodeSchema = z18.object({
3929
+ import { z as z20 } from "zod";
3930
+ var HttpDeleteInputNodeSchema = z20.object({
3581
3931
  route: RouteSchema,
3582
- queryParams: z18.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3583
- headers: z18.array(HeaderSchema).optional().describe("Headers configuration")
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 z19 } from "zod";
3697
- var HttpPatchInputNodeSchema = z19.object({
4046
+ import { z as z21 } from "zod";
4047
+ var HttpPatchInputNodeSchema = z21.object({
3698
4048
  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")
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomoz/workflows-nodes",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "description": "Atomoz Workflows - Node Library",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",