@atomoz/workflows-nodes 0.1.19 → 0.1.21

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
@@ -890,6 +890,21 @@ var IaAgentNode = {
890
890
  fieldType: "agent"
891
891
  }
892
892
  },
893
+ {
894
+ id: "sessionMemory",
895
+ label: "Session Memory",
896
+ type: "memory",
897
+ required: false,
898
+ typeable: false,
899
+ handle: {
900
+ type: "input",
901
+ label: "Session Memory",
902
+ name: "sessionMemory",
903
+ fieldType: "memory",
904
+ acceptTypes: ["memory"],
905
+ maxConnections: 1
906
+ }
907
+ },
893
908
  {
894
909
  id: "response",
895
910
  label: "Response",
@@ -902,13 +917,54 @@ var IaAgentNode = {
902
917
  name: "response",
903
918
  fieldType: "string"
904
919
  }
920
+ },
921
+ {
922
+ id: "beforeGuardrails",
923
+ label: "Before Guardrails",
924
+ type: "guardrail",
925
+ required: false,
926
+ typeable: false,
927
+ handle: {
928
+ type: "input",
929
+ label: "Before Guardrails",
930
+ name: "beforeGuardrails",
931
+ fieldType: "guardrail",
932
+ acceptTypes: ["guardrail"],
933
+ maxConnections: 10
934
+ }
935
+ },
936
+ {
937
+ id: "afterGuardrails",
938
+ label: "After Guardrails",
939
+ type: "guardrail",
940
+ required: false,
941
+ typeable: false,
942
+ handle: {
943
+ type: "input",
944
+ label: "After Guardrails",
945
+ name: "afterGuardrails",
946
+ fieldType: "guardrail",
947
+ acceptTypes: ["guardrail"],
948
+ maxConnections: 10
949
+ }
950
+ },
951
+ {
952
+ id: "guardrailMode",
953
+ label: "Guardrail Mode",
954
+ type: "select",
955
+ required: true,
956
+ defaultValue: "fail-first",
957
+ options: [
958
+ { label: "Fail on First Violation", value: "fail-first" },
959
+ { label: "Run All and Combine", value: "run-all" }
960
+ ]
905
961
  }
906
962
  ]
907
963
  };
908
964
 
909
965
  // src/nodes/ia/agent/function.ts
910
966
  import { createReactAgent } from "@langchain/langgraph/prebuilt";
911
- import { SystemMessage } from "@langchain/core/messages";
967
+ import { SystemMessage, HumanMessage } from "@langchain/core/messages";
912
968
 
913
969
  // src/utils/llm-factory.ts
914
970
  import { gql } from "graphql-request";
@@ -941,7 +997,7 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
941
997
  case "gemini":
942
998
  return new ChatGoogle({
943
999
  model: "gemini-flash-latest",
944
- apiKey: "AIzaSyAWS9GhesWxG4uTdJRQbBziMB1diXtXtlI",
1000
+ apiKey: "AIzaSyD9WiFuXp2fhVAokIMPp9YPKMlh7_Bvddc",
945
1001
  streaming
946
1002
  });
947
1003
  case "openai":
@@ -966,18 +1022,165 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
966
1022
  }
967
1023
  }
968
1024
 
1025
+ // src/utils/guardrail-executor.ts
1026
+ async function executeGuardrails(guardrails, content, mode = "fail-first") {
1027
+ const list = Array.isArray(guardrails) ? guardrails : [guardrails];
1028
+ const result = {
1029
+ passed: true,
1030
+ blocked: false,
1031
+ modifiedContent: content,
1032
+ violations: []
1033
+ };
1034
+ for (const guard of list) {
1035
+ if (!guard) continue;
1036
+ let guardPassed = true;
1037
+ let violationMessage = "";
1038
+ if (guard.type === "rule") {
1039
+ const { ruleType, config, action } = guard;
1040
+ if (ruleType === "keywords" && config) {
1041
+ const keywords = config.split(",").map((k) => k.trim().toLowerCase());
1042
+ const lowerContent = content.toLowerCase();
1043
+ const found = keywords.filter((k) => lowerContent.includes(k));
1044
+ if (found.length > 0) {
1045
+ guardPassed = false;
1046
+ violationMessage = `Conte\xFAdo cont\xE9m palavras proibidas: ${found.join(", ")}`;
1047
+ }
1048
+ } else if (ruleType === "regex" && config) {
1049
+ try {
1050
+ const regex = new RegExp(config, "i");
1051
+ if (regex.test(content)) {
1052
+ guardPassed = false;
1053
+ violationMessage = `Conte\xFAdo viola regra de padr\xE3o (regex): ${config}`;
1054
+ }
1055
+ } catch (e) {
1056
+ console.error("Invalid regex in guardrail:", config);
1057
+ }
1058
+ } else if (ruleType === "maxValue" && config) {
1059
+ const val = parseFloat(content.replace(/[^\d.-]/g, ""));
1060
+ const max = parseFloat(config);
1061
+ if (!isNaN(val) && val > max) {
1062
+ guardPassed = false;
1063
+ violationMessage = `Valor ${val} excede o m\xE1ximo permitido de ${max}.`;
1064
+ }
1065
+ } else if (ruleType === "minValue" && config) {
1066
+ const val = parseFloat(content.replace(/[^\d.-]/g, ""));
1067
+ const min = parseFloat(config);
1068
+ if (!isNaN(val) && val < min) {
1069
+ guardPassed = false;
1070
+ violationMessage = `Valor ${val} \xE9 menor que o m\xEDnimo permitido de ${min}.`;
1071
+ }
1072
+ }
1073
+ } else if (guard.type === "function") {
1074
+ const { nodeFunction, name } = guard;
1075
+ if (typeof nodeFunction === "function") {
1076
+ try {
1077
+ const result2 = await nodeFunction({
1078
+ input: content,
1079
+ fieldValues: { input: content },
1080
+ originalNodeData: guard.originalNodeData
1081
+ });
1082
+ if (result2 === false || typeof result2 === "object" && result2?.passed === false) {
1083
+ guardPassed = false;
1084
+ violationMessage = typeof result2?.message === "string" ? result2.message : `Fun\xE7\xE3o guardrail "${name}" reprovou o conte\xFAdo.`;
1085
+ } else if (typeof result2 === "object" && result2?.modifiedContent) {
1086
+ result2.modifiedContent = result2.modifiedContent;
1087
+ }
1088
+ } catch (error) {
1089
+ console.error(`Error executing function guardrail "${name}":`, error);
1090
+ guardPassed = false;
1091
+ violationMessage = `Erro na fun\xE7\xE3o guardrail: ${error instanceof Error ? error.message : String(error)}`;
1092
+ }
1093
+ }
1094
+ } else if (guard.type === "model") {
1095
+ const { model, evaluationPrompt, name } = guard;
1096
+ if (model && typeof model.invoke === "function") {
1097
+ try {
1098
+ const prompt = evaluationPrompt.replace("{{content}}", content);
1099
+ const response = await model.invoke(prompt);
1100
+ const resultText = typeof response.content === "string" ? response.content : String(response.content);
1101
+ if (resultText.toUpperCase().includes("UNSAFE")) {
1102
+ guardPassed = false;
1103
+ violationMessage = `Modelo de avalia\xE7\xE3o "${name}" detectou viola\xE7\xE3o de seguran\xE7a/pol\xEDtica.`;
1104
+ }
1105
+ } catch (error) {
1106
+ console.error(`Error executing model guardrail "${name}":`, error);
1107
+ }
1108
+ }
1109
+ }
1110
+ if (!guardPassed) {
1111
+ result.passed = false;
1112
+ result.violations.push({
1113
+ name: guard.name,
1114
+ message: violationMessage,
1115
+ action: guard.action || "block"
1116
+ });
1117
+ if (guard.action === "block") {
1118
+ result.blocked = true;
1119
+ result.message = violationMessage;
1120
+ if (mode === "fail-first") break;
1121
+ }
1122
+ }
1123
+ }
1124
+ return result;
1125
+ }
1126
+ function applyPromptGuardrails(systemMessage, guardrails) {
1127
+ const list = Array.isArray(guardrails) ? guardrails : [guardrails];
1128
+ let finalSystemMessage = systemMessage;
1129
+ for (const guard of list) {
1130
+ if (guard?.type === "prompt" && guard.prompt) {
1131
+ finalSystemMessage += `
1132
+
1133
+ GUARDRAIL [${guard.name}]: ${guard.prompt}`;
1134
+ }
1135
+ }
1136
+ return finalSystemMessage;
1137
+ }
1138
+
969
1139
  // src/nodes/ia/agent/function.ts
970
1140
  var IaAgentNodeFunction = async (inputs) => {
971
1141
  const { $field: _$field, $req: _$req, $inputs: _$inputs, $vars: _$vars } = inputs;
972
- const { model, tools, systemMessage, name, message } = inputs.fieldValues || {};
1142
+ const fieldValues = inputs.fieldValues || {};
1143
+ const { model, tools, systemMessage, name, message, beforeGuardrails, afterGuardrails, guardrailMode } = fieldValues;
973
1144
  const authToken = inputs.authToken;
974
1145
  const stream = Boolean(inputs?.stream);
975
1146
  const emitter = inputs?.emitter;
1147
+ const sessionMemory = fieldValues.sessionMemory || inputs.sessionMemory;
1148
+ const checkpointer = sessionMemory && typeof sessionMemory.put === "function" ? sessionMemory : sessionMemory?.checkpointer;
1149
+ const sessionId = inputs.sessionId || inputs.$req?.sessionId || `session-${Date.now()}`;
976
1150
  if (!name) {
977
1151
  throw new Error("Agent 'name' is required. Please provide a unique name for the agent in the node properties.");
978
1152
  }
979
- if (!model) {
980
- throw new Error("Model is required for IaAgentNode");
1153
+ const prepareGuardrails = async (list) => {
1154
+ const guardrailsList = Array.isArray(list) ? list : [list];
1155
+ return await Promise.all(guardrailsList.map(async (g) => {
1156
+ if (g?.type === "model" && g.model && !g.model.invoke) {
1157
+ if (!authToken) throw new Error("Auth token required for model guardrail");
1158
+ const modelInstance = await createLLMFromModel(g.model, authToken, false);
1159
+ return { ...g, model: modelInstance };
1160
+ }
1161
+ return g;
1162
+ }));
1163
+ };
1164
+ if (message && beforeGuardrails) {
1165
+ const preparedBefore = await prepareGuardrails(beforeGuardrails);
1166
+ const beforeResults = await executeGuardrails(preparedBefore, message, guardrailMode);
1167
+ if (beforeResults.blocked) {
1168
+ console.log(`\u{1F6E1}\uFE0F IaAgentNode "${name}": Blocked by before-agent guardrail:`, beforeResults.message);
1169
+ if (stream && emitter?.emitDelta) {
1170
+ emitter.emitDelta({
1171
+ content: beforeResults.message || "Requisi\xE7\xE3o bloqueada por pol\xEDtica de seguran\xE7a.",
1172
+ actor: name,
1173
+ isAgent: true,
1174
+ isError: true
1175
+ });
1176
+ }
1177
+ return {
1178
+ agent: null,
1179
+ output: beforeResults.message || "Requisi\xE7\xE3o bloqueada por pol\xEDtica de seguran\xE7a.",
1180
+ blocked: true,
1181
+ violations: beforeResults.violations
1182
+ };
1183
+ }
981
1184
  }
982
1185
  let toolsArray = [];
983
1186
  if (Array.isArray(tools)) {
@@ -985,9 +1188,15 @@ var IaAgentNodeFunction = async (inputs) => {
985
1188
  } else if (tools) {
986
1189
  toolsArray = [tools];
987
1190
  }
988
- const finalSystemMessageContent = `${systemMessage || ""}
1191
+ let finalSystemMessageContent = `${systemMessage || ""}
989
1192
 
990
1193
  IMPORTANT: You must base your response on the last message in the conversation history.`;
1194
+ if (beforeGuardrails) {
1195
+ finalSystemMessageContent = applyPromptGuardrails(finalSystemMessageContent, beforeGuardrails);
1196
+ }
1197
+ if (afterGuardrails) {
1198
+ finalSystemMessageContent = applyPromptGuardrails(finalSystemMessageContent, afterGuardrails);
1199
+ }
991
1200
  const finalSystemMessage = new SystemMessage(finalSystemMessageContent);
992
1201
  let llmInstance;
993
1202
  if (model?.integrationId) {
@@ -1003,17 +1212,25 @@ IMPORTANT: You must base your response on the last message in the conversation h
1003
1212
  const agent = createReactAgent({
1004
1213
  llm: llmInstance,
1005
1214
  tools: toolsArray,
1006
- messageModifier: finalSystemMessage
1215
+ messageModifier: finalSystemMessage,
1216
+ // Pass checkpointer directly for distributed memory
1217
+ ...checkpointer ? { checkpointer } : {}
1007
1218
  });
1008
1219
  agent.name = name;
1220
+ if (checkpointer) {
1221
+ console.log(`\u{1F9E0} IaAgentNode "${name}": Using distributed memory (sessionId: ${sessionId})`);
1222
+ } else {
1223
+ console.log(`\u26A0\uFE0F IaAgentNode "${name}": No sessionMemory connected - stateless mode`);
1224
+ }
1009
1225
  let output = "";
1010
1226
  if (message) {
1011
1227
  try {
1012
- const { HumanMessage: HumanMessage2 } = await import("@langchain/core/messages");
1228
+ const invokeConfig = checkpointer ? { configurable: { thread_id: sessionId } } : {};
1013
1229
  if (stream && emitter) {
1014
- const streamIterator = await agent.stream({
1015
- messages: [new HumanMessage2(message)]
1016
- });
1230
+ const streamIterator = await agent.stream(
1231
+ { messages: [new HumanMessage(message)] },
1232
+ invokeConfig
1233
+ );
1017
1234
  let lastMessages = [];
1018
1235
  const sentContents = /* @__PURE__ */ new Set();
1019
1236
  for await (const step of streamIterator) {
@@ -1057,9 +1274,10 @@ IMPORTANT: You must base your response on the last message in the conversation h
1057
1274
  }
1058
1275
  }
1059
1276
  } else {
1060
- const result = await agent.invoke({
1061
- messages: [new HumanMessage2(message)]
1062
- });
1277
+ const result = await agent.invoke(
1278
+ { messages: [new HumanMessage(message)] },
1279
+ invokeConfig
1280
+ );
1063
1281
  if (result?.messages && result.messages.length > 0) {
1064
1282
  const lastMessage = result.messages[result.messages.length - 1];
1065
1283
  const content = lastMessage?.content;
@@ -1076,6 +1294,26 @@ IMPORTANT: You must base your response on the last message in the conversation h
1076
1294
  }
1077
1295
  }
1078
1296
  }
1297
+ if (output && afterGuardrails) {
1298
+ const preparedAfter = await prepareGuardrails(afterGuardrails);
1299
+ const afterResults = await executeGuardrails(preparedAfter, output, guardrailMode);
1300
+ if (afterResults.blocked) {
1301
+ console.log(`\u{1F6E1}\uFE0F IaAgentNode "${name}": Response blocked by after-agent guardrail:`, afterResults.message);
1302
+ if (stream && emitter?.emitDelta) {
1303
+ emitter.emitDelta({
1304
+ content: `
1305
+
1306
+ \u26A0\uFE0F RESPOSTA BLOQUEADA: ${afterResults.message}`,
1307
+ actor: name,
1308
+ isAgent: true,
1309
+ isError: true
1310
+ });
1311
+ }
1312
+ output = afterResults.message || "Resposta bloqueada por pol\xEDtica de seguran\xE7a.";
1313
+ } else if (afterResults.modifiedContent) {
1314
+ output = afterResults.modifiedContent;
1315
+ }
1316
+ }
1079
1317
  } catch (error) {
1080
1318
  console.error("Error processing message in agent:", error);
1081
1319
  output = `Error: ${error instanceof Error ? error.message : "Unknown error"}`;
@@ -1157,6 +1395,21 @@ var AiSupervisorNode = {
1157
1395
  acceptTypes: ["agent"]
1158
1396
  }
1159
1397
  },
1398
+ {
1399
+ id: "sessionMemory",
1400
+ label: "Session Memory",
1401
+ type: "memory",
1402
+ required: false,
1403
+ typeable: false,
1404
+ handle: {
1405
+ type: "input",
1406
+ label: "Session Memory",
1407
+ name: "sessionMemory",
1408
+ fieldType: "memory",
1409
+ acceptTypes: ["memory"],
1410
+ maxConnections: 1
1411
+ }
1412
+ },
1160
1413
  {
1161
1414
  id: "response",
1162
1415
  label: "Response",
@@ -1175,9 +1428,8 @@ var AiSupervisorNode = {
1175
1428
 
1176
1429
  // src/nodes/ia/supervisor/function.ts
1177
1430
  import { createSupervisor } from "@langchain/langgraph-supervisor";
1178
- import { HumanMessage } from "@langchain/core/messages";
1179
- import { InMemoryStore, MemorySaver } from "@langchain/langgraph";
1180
- var checkpointer = new MemorySaver();
1431
+ import { HumanMessage as HumanMessage2 } from "@langchain/core/messages";
1432
+ import { InMemoryStore } from "@langchain/langgraph";
1181
1433
  var store = new InMemoryStore();
1182
1434
  var extractSupervisorAgents = (agents) => {
1183
1435
  if (Array.isArray(agents)) {
@@ -1233,6 +1485,9 @@ var AiSupervisorNodeFunction = async (params) => {
1233
1485
  const stream = (typeof outer.stream === "boolean" ? outer.stream : inner.stream) ?? false;
1234
1486
  const emitter = outer.emitter ?? inner.emitter;
1235
1487
  const authToken = outer.authToken ?? inner.authToken;
1488
+ const sessionMemory = inner.sessionMemory ?? outer.sessionMemory;
1489
+ const checkpointer = sessionMemory?.checkpointer;
1490
+ const sessionId = outer.sessionId || outer.$req?.sessionId || `supervisor-${Date.now()}`;
1236
1491
  if (!model) throw new Error("Model is required for AiSupervisorNode");
1237
1492
  if (!agents) throw new Error("Agents are required for AiSupervisorNode.");
1238
1493
  try {
@@ -1242,12 +1497,17 @@ var AiSupervisorNodeFunction = async (params) => {
1242
1497
  let llmInstance;
1243
1498
  if (model?.model && model?.integrationId) {
1244
1499
  if (!authToken) {
1245
- throw new Error("Auth token is required to instantiate LLM from integration 3");
1500
+ throw new Error("Auth token is required to instantiate LLM from integration");
1246
1501
  }
1247
1502
  llmInstance = await createLLMFromModel(model, authToken, stream);
1248
1503
  } else {
1249
1504
  llmInstance = model;
1250
1505
  }
1506
+ if (checkpointer) {
1507
+ console.log(`\u{1F9E0} AiSupervisorNode: Using distributed memory (sessionId: ${sessionId})`);
1508
+ } else {
1509
+ console.log(`\u26A0\uFE0F AiSupervisorNode: No sessionMemory connected - stateless mode`);
1510
+ }
1251
1511
  const finalSystemPrompt = systemMessage || "You are a supervisor...";
1252
1512
  const workflow = createSupervisor({
1253
1513
  llm: llmInstance,
@@ -1255,14 +1515,14 @@ var AiSupervisorNodeFunction = async (params) => {
1255
1515
  prompt: finalSystemPrompt
1256
1516
  });
1257
1517
  const app = workflow.compile({
1258
- checkpointer,
1518
+ ...checkpointer ? { checkpointer } : {},
1259
1519
  store
1260
1520
  });
1261
1521
  if (stream && emitter) {
1262
1522
  try {
1263
1523
  const streamIterator = await app.stream(
1264
- { messages: [new HumanMessage({ content: message })] },
1265
- { recursionLimit: 150, configurable: { thread_id: "conversation" } }
1524
+ { messages: [new HumanMessage2({ content: message })] },
1525
+ { recursionLimit: 150, configurable: { thread_id: sessionId } }
1266
1526
  );
1267
1527
  let finalMessages = [];
1268
1528
  const previousStepMessages = /* @__PURE__ */ new Map();
@@ -1340,8 +1600,8 @@ var AiSupervisorNodeFunction = async (params) => {
1340
1600
  }
1341
1601
  } else {
1342
1602
  const result = await app.invoke(
1343
- { messages: [new HumanMessage({ content: message })] },
1344
- { recursionLimit: 150, configurable: { thread_id: "conversation" } }
1603
+ { messages: [new HumanMessage2({ content: message })] },
1604
+ { recursionLimit: 150, configurable: { thread_id: sessionId } }
1345
1605
  );
1346
1606
  const finalResponse = extractFinalResponse(result?.messages);
1347
1607
  return {
@@ -1435,12 +1695,139 @@ var AiToolNode = {
1435
1695
  // src/nodes/ia/tool/function.ts
1436
1696
  import { tool } from "@langchain/core/tools";
1437
1697
 
1698
+ // src/nodes/memory/postgres/data.ts
1699
+ import { z as z8 } from "zod";
1700
+ var PostgresMemoryNodeSchema = z8.object({
1701
+ connectionString: z8.string().describe("PostgreSQL connection string")
1702
+ });
1703
+ var PostgresMemoryNode = {
1704
+ label: "Postgres Memory",
1705
+ type: "PostgresMemoryNode",
1706
+ category: "memory",
1707
+ description: "Persistent conversation memory using PostgreSQL (distributed across pods)",
1708
+ icon: "\u{1F418}",
1709
+ group: "Memory",
1710
+ tags: {
1711
+ execution: "sync",
1712
+ group: "Memory"
1713
+ },
1714
+ fields: [
1715
+ {
1716
+ id: "connectionString",
1717
+ label: "Connection String",
1718
+ type: "string",
1719
+ required: true,
1720
+ defaultValue: "postgresql://yugabyte:yugabyte@localhost:5433/workflows",
1721
+ placeholder: "postgresql://user:pass@host:5432/database"
1722
+ },
1723
+ {
1724
+ id: "checkpointer",
1725
+ label: "Checkpointer",
1726
+ type: "memory",
1727
+ required: true,
1728
+ typeable: false,
1729
+ handle: {
1730
+ type: "output",
1731
+ label: "Memory",
1732
+ name: "checkpointer",
1733
+ fieldType: "memory"
1734
+ }
1735
+ }
1736
+ ]
1737
+ };
1738
+
1739
+ // src/nodes/memory/postgres/function.ts
1740
+ import { PostgresSaver } from "@langchain/langgraph-checkpoint-postgres";
1741
+ var PostgresMemoryNodeFunction = async (inputs) => {
1742
+ const { $field: _$field, $req: _$req, $inputs: _$inputs, $vars: _$vars } = inputs;
1743
+ const fieldValues = inputs.fieldValues || {};
1744
+ const connectionString = fieldValues.connectionString || inputs.connectionString || "postgresql://postgres:postgres@localhost:5432/workflows";
1745
+ try {
1746
+ const checkpointer = PostgresSaver.fromConnString(connectionString);
1747
+ await checkpointer.setup();
1748
+ console.log("\u2705 PostgresMemory: Checkpointer initialized");
1749
+ return {
1750
+ checkpointer,
1751
+ type: "PostgresMemoryNode",
1752
+ connectionString: connectionString.replace(/:[^:@]+@/, ":***@")
1753
+ // Hide password in output
1754
+ };
1755
+ } catch (error) {
1756
+ console.error("\u274C PostgresMemory: Failed to initialize checkpointer:", error);
1757
+ throw new Error(`PostgresMemory initialization failed: ${error instanceof Error ? error.message : String(error)}`);
1758
+ }
1759
+ };
1760
+
1761
+ // src/nodes/memory/redis/data.ts
1762
+ import { z as z9 } from "zod";
1763
+ var RedisMemoryNodeSchema = z9.object({
1764
+ redisUrl: z9.string().describe("Redis connection URL")
1765
+ });
1766
+ var RedisMemoryNode = {
1767
+ label: "Redis Memory",
1768
+ type: "RedisMemoryNode",
1769
+ category: "memory",
1770
+ description: "Fast, persistent conversation memory using Redis (distributed across pods)",
1771
+ icon: "\u{1F534}",
1772
+ group: "Memory",
1773
+ tags: {
1774
+ execution: "sync",
1775
+ group: "Memory"
1776
+ },
1777
+ fields: [
1778
+ {
1779
+ id: "redisUrl",
1780
+ label: "Redis URL",
1781
+ type: "string",
1782
+ required: true,
1783
+ defaultValue: "redis://localhost:6379",
1784
+ placeholder: "redis://localhost:6379"
1785
+ },
1786
+ {
1787
+ id: "checkpointer",
1788
+ label: "Checkpointer",
1789
+ type: "memory",
1790
+ required: true,
1791
+ typeable: false,
1792
+ handle: {
1793
+ type: "output",
1794
+ label: "Memory",
1795
+ name: "checkpointer",
1796
+ fieldType: "memory"
1797
+ }
1798
+ }
1799
+ ]
1800
+ };
1801
+
1802
+ // src/nodes/memory/redis/function.ts
1803
+ import { RedisSaver } from "@langchain/langgraph-checkpoint-redis";
1804
+ var RedisMemoryNodeFunction = async (inputs) => {
1805
+ const { $field: _$field, $req: _$req, $inputs: _$inputs, $vars: _$vars } = inputs;
1806
+ const fieldValues = inputs.fieldValues || {};
1807
+ const redisUrl = fieldValues.redisUrl || inputs.redisUrl || "redis://localhost:6379";
1808
+ try {
1809
+ const checkpointer = await RedisSaver.fromUrl(redisUrl);
1810
+ console.log("\u2705 RedisMemory: Checkpointer initialized");
1811
+ return {
1812
+ checkpointer,
1813
+ type: "RedisMemoryNode",
1814
+ redisUrl: redisUrl.replace(/:[^:@]+@/, ":***@")
1815
+ // Hide password in output
1816
+ };
1817
+ } catch (error) {
1818
+ console.error("\u274C RedisMemory: Failed to initialize checkpointer:", error);
1819
+ throw new Error(`RedisMemory initialization failed: ${error instanceof Error ? error.message : String(error)}`);
1820
+ }
1821
+ };
1822
+
1438
1823
  // src/nodes/consts/schemas.ts
1439
1824
  var schemas = {
1440
1825
  IaAgentNode: IaAgentNodeSchema,
1441
1826
  AiSupervisorNode: AiSupervisorNodeSchema,
1442
1827
  AiToolNode: AiToolNodeSchema,
1443
- IaMessageNode: IaMessageNodeSchema
1828
+ IaMessageNode: IaMessageNodeSchema,
1829
+ PostgresMemoryNode: PostgresMemoryNodeSchema,
1830
+ RedisMemoryNode: RedisMemoryNodeSchema
1444
1831
  };
1445
1832
 
1446
1833
  // src/nodes/ia/tool/function.ts
@@ -1482,11 +1869,11 @@ var AiToolNodeFunction = async (params) => {
1482
1869
  };
1483
1870
 
1484
1871
  // src/nodes/ia/message/message.ts
1485
- import { z as z8 } from "zod";
1486
- var IaMessageNodeSchema = z8.object({
1487
- model: z8.any().describe("LLM model to use"),
1488
- systemMessage: z8.string().optional().describe("System message for context"),
1489
- message: z8.string().describe("User message to send to the LLM")
1872
+ import { z as z10 } from "zod";
1873
+ var IaMessageNodeSchema = z10.object({
1874
+ model: z10.any().describe("LLM model to use"),
1875
+ systemMessage: z10.string().optional().describe("System message for context"),
1876
+ message: z10.string().describe("User message to send to the LLM")
1490
1877
  });
1491
1878
  var IaMessageNodeFunction = async (inputs) => {
1492
1879
  const { $field: _$field, $req: _$req, $inputs: _$inputs_var, $vars: _$vars } = inputs;
@@ -1621,10 +2008,10 @@ var IaMessageNode = {
1621
2008
  };
1622
2009
 
1623
2010
  // src/nodes/social/whatsapp/send-template/data.ts
1624
- import { z as z9 } from "zod";
1625
- var WhatsappSendTemplateNodeSchema = z9.object({
1626
- phoneNumber: z9.string().describe("Phone number to send the message to"),
1627
- message: z9.string().describe("Message to send")
2011
+ import { z as z11 } from "zod";
2012
+ var WhatsappSendTemplateNodeSchema = z11.object({
2013
+ phoneNumber: z11.string().describe("Phone number to send the message to"),
2014
+ message: z11.string().describe("Message to send")
1628
2015
  });
1629
2016
  var WhatsappSendTemplateNode = {
1630
2017
  label: "Whatsapp Send Template",
@@ -1665,10 +2052,10 @@ var WhatsappSendTemplateNode = {
1665
2052
  };
1666
2053
 
1667
2054
  // src/nodes/social/whatsapp/send-message/data.ts
1668
- import { z as z10 } from "zod";
1669
- var WhatsappSendMessageNodeSchema = z10.object({
1670
- phoneNumber: z10.string().describe("Phone number to send the message to"),
1671
- message: z10.string().describe("Message content to send")
2055
+ import { z as z12 } from "zod";
2056
+ var WhatsappSendMessageNodeSchema = z12.object({
2057
+ phoneNumber: z12.string().describe("Phone number to send the message to"),
2058
+ message: z12.string().describe("Message content to send")
1672
2059
  });
1673
2060
  var WhatsappSendMessageNode = {
1674
2061
  label: "Whatsapp Send Message",
@@ -1882,6 +2269,375 @@ var CustomCodeNode = {
1882
2269
  ]
1883
2270
  };
1884
2271
 
2272
+ // src/nodes/guardrails/prompt/data.ts
2273
+ import { z as z13 } from "zod";
2274
+ var PromptGuardrailNodeSchema = z13.object({
2275
+ name: z13.string().describe("Nome do guardrail"),
2276
+ prompt: z13.string().describe("Instru\xE7\xE3o do guardrail")
2277
+ });
2278
+ var PromptGuardrailNode = {
2279
+ label: "Prompt Guardrail",
2280
+ type: "PromptGuardrailNode",
2281
+ category: "step",
2282
+ description: "Injeta instru\xE7\xF5es de seguran\xE7a ou comportamento no sistema do agente",
2283
+ icon: "\u{1F6E1}\uFE0F",
2284
+ group: "Guardrails",
2285
+ tags: {
2286
+ execution: "sync",
2287
+ group: "Guardrails"
2288
+ },
2289
+ fields: [
2290
+ {
2291
+ id: "name",
2292
+ label: "Nome",
2293
+ type: "string",
2294
+ required: true,
2295
+ placeholder: "Ex: Enforce Portuguese"
2296
+ },
2297
+ {
2298
+ id: "prompt",
2299
+ label: "Instru\xE7\xE3o",
2300
+ type: "textarea",
2301
+ required: true,
2302
+ placeholder: "Ex: Sempre responda em portugu\xEAs brasileiro"
2303
+ },
2304
+ {
2305
+ id: "guardrail",
2306
+ label: "Guardrail",
2307
+ type: "guardrail",
2308
+ required: true,
2309
+ typeable: false,
2310
+ handle: {
2311
+ type: "output",
2312
+ label: "Guardrail",
2313
+ name: "guardrail",
2314
+ fieldType: "guardrail"
2315
+ }
2316
+ }
2317
+ ]
2318
+ };
2319
+
2320
+ // src/nodes/guardrails/prompt/function.ts
2321
+ var PromptGuardrailNodeFunction = async (inputs) => {
2322
+ const { fieldValues = {} } = inputs;
2323
+ const { name, prompt } = fieldValues;
2324
+ return {
2325
+ type: "prompt",
2326
+ name: name || "Prompt Guardrail",
2327
+ prompt: prompt || ""
2328
+ };
2329
+ };
2330
+
2331
+ // src/nodes/guardrails/rule/data.ts
2332
+ import { z as z14 } from "zod";
2333
+ var RuleGuardrailNodeSchema = z14.object({
2334
+ name: z14.string().describe("Nome do guardrail"),
2335
+ phase: z14.enum(["before", "after"]).describe("Fase de execu\xE7\xE3o"),
2336
+ ruleType: z14.enum(["maxValue", "minValue", "regex", "keywords", "pii"]).describe("Tipo de regra"),
2337
+ config: z14.any().describe("Configura\xE7\xE3o da regra"),
2338
+ action: z14.enum(["block", "warn", "modify"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o")
2339
+ });
2340
+ var RuleGuardrailNode = {
2341
+ label: "Rule Guardrail",
2342
+ type: "RuleGuardrailNode",
2343
+ category: "step",
2344
+ description: "Valida\xE7\xF5es determin\xEDsticas baseadas em regras (limites, palavras-chave, regex)",
2345
+ icon: "\u2696\uFE0F",
2346
+ group: "Guardrails",
2347
+ tags: {
2348
+ execution: "sync",
2349
+ group: "Guardrails"
2350
+ },
2351
+ fields: [
2352
+ {
2353
+ id: "name",
2354
+ label: "Nome",
2355
+ type: "string",
2356
+ required: true,
2357
+ placeholder: "Ex: Limit Discount"
2358
+ },
2359
+ {
2360
+ id: "phase",
2361
+ label: "Fase",
2362
+ type: "select",
2363
+ required: true,
2364
+ defaultValue: "after",
2365
+ options: [
2366
+ { label: "Antes do Agente (Input)", value: "before" },
2367
+ { label: "Depois do Agente (Output)", value: "after" }
2368
+ ]
2369
+ },
2370
+ {
2371
+ id: "ruleType",
2372
+ label: "Tipo de Regra",
2373
+ type: "select",
2374
+ required: true,
2375
+ options: [
2376
+ { label: "Valor M\xE1ximo", value: "maxValue" },
2377
+ { label: "Valor M\xEDnimo", value: "minValue" },
2378
+ { label: "Express\xE3o Regular (Regex)", value: "regex" },
2379
+ { label: "Palavras-chave (Keywords)", value: "keywords" },
2380
+ { label: "Dados Sens\xEDveis (PII)", value: "pii" }
2381
+ ]
2382
+ },
2383
+ {
2384
+ id: "config",
2385
+ label: "Configura\xE7\xE3o",
2386
+ type: "string",
2387
+ required: true,
2388
+ placeholder: "Ex: 15 (para valor) ou ofensivo,hack (para keywords)"
2389
+ },
2390
+ {
2391
+ id: "action",
2392
+ label: "A\xE7\xE3o em Viola\xE7\xE3o",
2393
+ type: "select",
2394
+ required: true,
2395
+ defaultValue: "block",
2396
+ options: [
2397
+ { label: "Bloquear Resposta", value: "block" },
2398
+ { label: "Avisar (Warning)", value: "warn" },
2399
+ { label: "Modificar/Ocultar", value: "modify" }
2400
+ ]
2401
+ },
2402
+ {
2403
+ id: "guardrail",
2404
+ label: "Guardrail",
2405
+ type: "guardrail",
2406
+ required: true,
2407
+ typeable: false,
2408
+ handle: {
2409
+ type: "output",
2410
+ label: "Guardrail",
2411
+ name: "guardrail",
2412
+ fieldType: "guardrail"
2413
+ }
2414
+ }
2415
+ ]
2416
+ };
2417
+
2418
+ // src/nodes/guardrails/rule/function.ts
2419
+ var RuleGuardrailNodeFunction = async (inputs) => {
2420
+ const { fieldValues = {} } = inputs;
2421
+ const { name, phase, ruleType, config, action } = fieldValues;
2422
+ return {
2423
+ type: "rule",
2424
+ name: name || "Rule Guardrail",
2425
+ phase: phase || "after",
2426
+ ruleType: ruleType || "keywords",
2427
+ config: config || "",
2428
+ action: action || "block"
2429
+ };
2430
+ };
2431
+
2432
+ // src/nodes/guardrails/function/data.ts
2433
+ import { z as z15 } from "zod";
2434
+ var FunctionGuardrailNodeSchema = z15.object({
2435
+ name: z15.string().describe("Nome do guardrail"),
2436
+ phase: z15.enum(["before", "after"]).describe("Fase de execu\xE7\xE3o"),
2437
+ description: z15.string().optional().describe("Descri\xE7\xE3o do que a fun\xE7\xE3o valida"),
2438
+ action: z15.enum(["block", "warn", "modify", "escalate"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o")
2439
+ });
2440
+ var FunctionGuardrailNode = {
2441
+ label: "Function Guardrail",
2442
+ type: "FunctionGuardrailNode",
2443
+ category: "step",
2444
+ description: "Executa uma fun\xE7\xE3o customizada (Custom Code ou HTTP) para validar entrada/sa\xEDda",
2445
+ icon: "\u{1F9E9}",
2446
+ group: "Guardrails",
2447
+ tags: {
2448
+ execution: "async",
2449
+ group: "Guardrails"
2450
+ },
2451
+ fields: [
2452
+ {
2453
+ id: "name",
2454
+ label: "Nome",
2455
+ type: "string",
2456
+ required: true,
2457
+ placeholder: "Ex: Validar Desconto API"
2458
+ },
2459
+ {
2460
+ id: "phase",
2461
+ label: "Fase",
2462
+ type: "select",
2463
+ required: true,
2464
+ defaultValue: "after",
2465
+ options: [
2466
+ { label: "Antes do Agente (Input)", value: "before" },
2467
+ { label: "Depois do Agente (Output)", value: "after" }
2468
+ ]
2469
+ },
2470
+ {
2471
+ id: "description",
2472
+ label: "Descri\xE7\xE3o",
2473
+ type: "textarea",
2474
+ required: false,
2475
+ placeholder: "Descreva o que este guardrail valida..."
2476
+ },
2477
+ {
2478
+ id: "function",
2479
+ label: "Fun\xE7\xE3o",
2480
+ type: "function",
2481
+ required: true,
2482
+ typeable: false,
2483
+ handle: {
2484
+ type: "input",
2485
+ label: "Fun\xE7\xE3o",
2486
+ name: "function",
2487
+ fieldType: "function",
2488
+ acceptTypes: ["code", "http", "any"],
2489
+ maxConnections: 1
2490
+ }
2491
+ },
2492
+ {
2493
+ id: "action",
2494
+ label: "A\xE7\xE3o em Viola\xE7\xE3o",
2495
+ type: "select",
2496
+ required: true,
2497
+ defaultValue: "block",
2498
+ options: [
2499
+ { label: "Bloquear", value: "block" },
2500
+ { label: "Avisar (Warning)", value: "warn" },
2501
+ { label: "Modificar", value: "modify" },
2502
+ { label: "Escalar (Human-in-the-loop)", value: "escalate" }
2503
+ ]
2504
+ },
2505
+ {
2506
+ id: "guardrail",
2507
+ label: "Guardrail",
2508
+ type: "guardrail",
2509
+ required: true,
2510
+ typeable: false,
2511
+ handle: {
2512
+ type: "output",
2513
+ label: "Guardrail",
2514
+ name: "guardrail",
2515
+ fieldType: "guardrail"
2516
+ }
2517
+ }
2518
+ ]
2519
+ };
2520
+
2521
+ // src/nodes/guardrails/function/function.ts
2522
+ var FunctionGuardrailNodeFunction = async (inputs) => {
2523
+ const { fieldValues = {} } = inputs;
2524
+ const {
2525
+ name,
2526
+ phase,
2527
+ description,
2528
+ action,
2529
+ nodeFunction,
2530
+ nodeType,
2531
+ originalNodeData
2532
+ } = fieldValues;
2533
+ return {
2534
+ type: "function",
2535
+ name: name || "Function Guardrail",
2536
+ phase: phase || "after",
2537
+ description: description || "",
2538
+ action: action || "block",
2539
+ // Injected by executeWorkflow.ts
2540
+ nodeFunction,
2541
+ nodeType,
2542
+ originalNodeData
2543
+ };
2544
+ };
2545
+
2546
+ // src/nodes/guardrails/model/data.ts
2547
+ import { z as z16 } from "zod";
2548
+ var ModelGuardrailNodeSchema = z16.object({
2549
+ name: z16.string().describe("Nome do guardrail"),
2550
+ evaluationPrompt: z16.string().describe("Prompt de avalia\xE7\xE3o"),
2551
+ model: z16.any().describe("Modelo LLM para avalia\xE7\xE3o"),
2552
+ action: z16.enum(["block", "warn", "escalate"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o")
2553
+ });
2554
+ var ModelGuardrailNode = {
2555
+ label: "Model Guardrail",
2556
+ type: "ModelGuardrailNode",
2557
+ category: "step",
2558
+ description: "Usa um modelo de IA secund\xE1rio para avaliar a seguran\xE7a ou qualidade do conte\xFAdo",
2559
+ icon: "\u{1F9E0}\u{1F6E1}\uFE0F",
2560
+ group: "Guardrails",
2561
+ tags: {
2562
+ execution: "async",
2563
+ group: "Guardrails"
2564
+ },
2565
+ fields: [
2566
+ {
2567
+ id: "name",
2568
+ label: "Nome",
2569
+ type: "string",
2570
+ required: true,
2571
+ placeholder: "Ex: Safety Check"
2572
+ },
2573
+ {
2574
+ id: "evaluationPrompt",
2575
+ label: "Prompt de Avalia\xE7\xE3o",
2576
+ type: "textarea",
2577
+ required: true,
2578
+ placeholder: "Ex: Avalie se a resposta abaixo cont\xE9m discurso de \xF3dio ou ofensas. Responda apenas SAFE ou UNSAFE.",
2579
+ defaultValue: "Analise se o conte\xFAdo a seguir \xE9 apropriado, seguro e segue as pol\xEDticas de \xE9tica. Responda 'SAFE' se estiver tudo bem ou 'UNSAFE' caso contr\xE1rio.\n\nCONTE\xDADO:\n{{content}}"
2580
+ },
2581
+ {
2582
+ id: "model",
2583
+ label: "Modelo de Avalia\xE7\xE3o",
2584
+ type: "model",
2585
+ required: true,
2586
+ handle: {
2587
+ type: "input",
2588
+ label: "Modelo",
2589
+ name: "model",
2590
+ fieldType: "model",
2591
+ acceptTypes: ["model"],
2592
+ maxConnections: 1
2593
+ }
2594
+ },
2595
+ {
2596
+ id: "action",
2597
+ label: "A\xE7\xE3o em Viola\xE7\xE3o (UNSAFE)",
2598
+ type: "select",
2599
+ required: true,
2600
+ defaultValue: "block",
2601
+ options: [
2602
+ { label: "Bloquear Resposta", value: "block" },
2603
+ { label: "Avisar (Warning)", value: "warn" },
2604
+ { label: "Escalar (Human-in-the-loop)", value: "escalate" }
2605
+ ]
2606
+ },
2607
+ {
2608
+ id: "guardrail",
2609
+ label: "Guardrail",
2610
+ type: "guardrail",
2611
+ required: true,
2612
+ typeable: false,
2613
+ handle: {
2614
+ type: "output",
2615
+ label: "Guardrail",
2616
+ name: "guardrail",
2617
+ fieldType: "guardrail"
2618
+ }
2619
+ }
2620
+ ]
2621
+ };
2622
+
2623
+ // src/nodes/guardrails/model/function.ts
2624
+ var ModelGuardrailNodeFunction = async (inputs) => {
2625
+ const { fieldValues = {} } = inputs;
2626
+ const {
2627
+ name,
2628
+ evaluationPrompt,
2629
+ model,
2630
+ action
2631
+ } = fieldValues;
2632
+ return {
2633
+ type: "model",
2634
+ name: name || "Model Guardrail",
2635
+ evaluationPrompt: evaluationPrompt || "Avalie se este conte\xFAdo \xE9 seguro. Responda apenas SAFE ou UNSAFE.",
2636
+ model,
2637
+ action: action || "block"
2638
+ };
2639
+ };
2640
+
1885
2641
  // src/nodes/consts/nodes.ts
1886
2642
  var nodes = [
1887
2643
  ChatInputNode,
@@ -1899,10 +2655,16 @@ var nodes = [
1899
2655
  IaAgentNode,
1900
2656
  AiToolNode,
1901
2657
  AiSupervisorNode,
2658
+ PostgresMemoryNode,
2659
+ RedisMemoryNode,
1902
2660
  WhatsappSendTemplateNode,
1903
2661
  WhatsappSendMessageNode,
1904
2662
  WhatsappMessageTriggerNode,
1905
- CustomCodeNode
2663
+ CustomCodeNode,
2664
+ PromptGuardrailNode,
2665
+ RuleGuardrailNode,
2666
+ FunctionGuardrailNode,
2667
+ ModelGuardrailNode
1906
2668
  ];
1907
2669
  var nodes_default = nodes;
1908
2670
 
@@ -2018,7 +2780,13 @@ var nodeFunctions = {
2018
2780
  WhatsappNode: WhatsappStartChatFunction,
2019
2781
  WhatsappSendMessageNode: WhatsappSendMessageFunction,
2020
2782
  CustomCodeNode: NodeFunction,
2021
- CustomNode: CustomNodeFunction
2783
+ CustomNode: CustomNodeFunction,
2784
+ PostgresMemoryNode: PostgresMemoryNodeFunction,
2785
+ RedisMemoryNode: RedisMemoryNodeFunction,
2786
+ PromptGuardrailNode: PromptGuardrailNodeFunction,
2787
+ RuleGuardrailNode: RuleGuardrailNodeFunction,
2788
+ FunctionGuardrailNode: FunctionGuardrailNodeFunction,
2789
+ ModelGuardrailNode: ModelGuardrailNodeFunction
2022
2790
  };
2023
2791
  var node_functions_default = nodeFunctions;
2024
2792
 
@@ -2132,12 +2900,12 @@ var HttpPutInputNodeFunction = (params) => {
2132
2900
  };
2133
2901
 
2134
2902
  // src/nodes/inputs/http/put/schema.ts
2135
- import { z as z11 } from "zod";
2136
- var HttpPutInputNodeSchema = z11.object({
2903
+ import { z as z17 } from "zod";
2904
+ var HttpPutInputNodeSchema = z17.object({
2137
2905
  route: RouteSchema,
2138
- queryParams: z11.array(QueryParamSchema).optional().describe("Query parameters configuration"),
2139
- headers: z11.array(HeaderSchema).optional().describe("Headers configuration"),
2140
- body: z11.array(BodyFieldSchema).optional().describe("Body fields configuration")
2906
+ queryParams: z17.array(QueryParamSchema).optional().describe("Query parameters configuration"),
2907
+ headers: z17.array(HeaderSchema).optional().describe("Headers configuration"),
2908
+ body: z17.array(BodyFieldSchema).optional().describe("Body fields configuration")
2141
2909
  });
2142
2910
 
2143
2911
  // src/nodes/inputs/http/delete/data.ts
@@ -2229,11 +2997,11 @@ var HttpDeleteInputNodeFunction = async (params) => {
2229
2997
  };
2230
2998
 
2231
2999
  // src/nodes/inputs/http/delete/schema.ts
2232
- import { z as z12 } from "zod";
2233
- var HttpDeleteInputNodeSchema = z12.object({
3000
+ import { z as z18 } from "zod";
3001
+ var HttpDeleteInputNodeSchema = z18.object({
2234
3002
  route: RouteSchema,
2235
- queryParams: z12.array(QueryParamSchema).optional().describe("Query parameters configuration"),
2236
- headers: z12.array(HeaderSchema).optional().describe("Headers configuration")
3003
+ queryParams: z18.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3004
+ headers: z18.array(HeaderSchema).optional().describe("Headers configuration")
2237
3005
  });
2238
3006
 
2239
3007
  // src/nodes/inputs/http/patch/data.ts
@@ -2346,12 +3114,12 @@ var HttpPatchInputNodeFunction = (params) => {
2346
3114
  };
2347
3115
 
2348
3116
  // src/nodes/inputs/http/patch/schema.ts
2349
- import { z as z13 } from "zod";
2350
- var HttpPatchInputNodeSchema = z13.object({
3117
+ import { z as z19 } from "zod";
3118
+ var HttpPatchInputNodeSchema = z19.object({
2351
3119
  route: RouteSchema,
2352
- queryParams: z13.array(QueryParamSchema).optional().describe("Query parameters configuration"),
2353
- headers: z13.array(HeaderSchema).optional().describe("Headers configuration"),
2354
- body: z13.array(BodyFieldSchema).optional().describe("Body fields configuration")
3120
+ queryParams: z19.array(QueryParamSchema).optional().describe("Query parameters configuration"),
3121
+ headers: z19.array(HeaderSchema).optional().describe("Headers configuration"),
3122
+ body: z19.array(BodyFieldSchema).optional().describe("Body fields configuration")
2355
3123
  });
2356
3124
 
2357
3125
  // src/nodes/inputs/http/utils.ts