@atomoz/workflows-nodes 0.1.22 → 0.1.24

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
@@ -993,39 +993,50 @@ var IaAgentNode = {
993
993
  typeable: false,
994
994
  handle: {
995
995
  type: "output",
996
- label: "response",
996
+ label: "Response",
997
997
  name: "response",
998
998
  fieldType: "string"
999
999
  }
1000
1000
  },
1001
1001
  {
1002
- id: "beforeGuardrails",
1003
- label: "Before Guardrails",
1004
- type: "guardrail",
1002
+ id: "blocked",
1003
+ label: "Is Blocked",
1004
+ type: "boolean",
1005
1005
  required: false,
1006
1006
  typeable: false,
1007
1007
  handle: {
1008
- type: "input",
1009
- label: "Before Guardrails",
1010
- name: "beforeGuardrails",
1011
- fieldType: "guardrail",
1012
- acceptTypes: ["guardrail"],
1013
- maxConnections: 10
1008
+ type: "output",
1009
+ label: "Blocked",
1010
+ name: "blocked",
1011
+ fieldType: "boolean"
1012
+ }
1013
+ },
1014
+ {
1015
+ id: "violations",
1016
+ label: "Violations",
1017
+ type: "json",
1018
+ required: false,
1019
+ typeable: false,
1020
+ handle: {
1021
+ type: "output",
1022
+ label: "Violations",
1023
+ name: "violations",
1024
+ fieldType: "json"
1014
1025
  }
1015
1026
  },
1016
1027
  {
1017
- id: "afterGuardrails",
1018
- label: "After Guardrails",
1028
+ id: "guardrails",
1029
+ label: "Guardrails (Todas as Fases)",
1019
1030
  type: "guardrail",
1020
1031
  required: false,
1021
1032
  typeable: false,
1022
1033
  handle: {
1023
1034
  type: "input",
1024
- label: "After Guardrails",
1025
- name: "afterGuardrails",
1035
+ label: "Guardrails",
1036
+ name: "guardrails",
1026
1037
  fieldType: "guardrail",
1027
1038
  acceptTypes: ["guardrail"],
1028
- maxConnections: 10
1039
+ maxConnections: 20
1029
1040
  }
1030
1041
  },
1031
1042
  {
@@ -1077,7 +1088,7 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
1077
1088
  case "gemini":
1078
1089
  return new import_google_gauth.ChatGoogle({
1079
1090
  model: "gemini-flash-latest",
1080
- apiKey: "AIzaSyD9WiFuXp2fhVAokIMPp9YPKMlh7_Bvddc",
1091
+ apiKey: "AIzaSyBzrL8Hx6dHhXgwc2HfLlQsf5Y-9pdtc9M",
1081
1092
  streaming
1082
1093
  });
1083
1094
  case "openai":
@@ -1103,7 +1114,7 @@ async function createLLMFromModel(modelConfig, authToken, streaming = false) {
1103
1114
  }
1104
1115
 
1105
1116
  // src/utils/guardrail-executor.ts
1106
- async function executeGuardrails(guardrails, content, mode = "fail-first") {
1117
+ async function executeGuardrails(guardrails, content, mode = "fail-first", context = {}) {
1107
1118
  const list = Array.isArray(guardrails) ? guardrails : [guardrails];
1108
1119
  const result = {
1109
1120
  passed: true,
@@ -1116,7 +1127,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first") {
1116
1127
  let guardPassed = true;
1117
1128
  let violationMessage = "";
1118
1129
  if (guard.type === "rule") {
1119
- const { ruleType, config, action } = guard;
1130
+ const { ruleType, config, action, actionInstruction } = guard;
1120
1131
  if (ruleType === "keywords" && config) {
1121
1132
  const keywords = config.split(",").map((k) => k.trim().toLowerCase());
1122
1133
  const lowerContent = content.toLowerCase();
@@ -1150,18 +1161,33 @@ async function executeGuardrails(guardrails, content, mode = "fail-first") {
1150
1161
  violationMessage = `Valor ${val} \xE9 menor que o m\xEDnimo permitido de ${min}.`;
1151
1162
  }
1152
1163
  }
1164
+ if (!guardPassed && actionInstruction) {
1165
+ violationMessage = actionInstruction;
1166
+ }
1153
1167
  } else if (guard.type === "function") {
1154
- const { nodeFunction, name } = guard;
1168
+ const { nodeFunction, name, actionInstruction } = guard;
1155
1169
  if (typeof nodeFunction === "function") {
1156
1170
  try {
1171
+ const executionContext = {
1172
+ input: content,
1173
+ ...context
1174
+ };
1157
1175
  const result2 = await nodeFunction({
1158
1176
  input: content,
1159
- fieldValues: { input: content },
1160
- originalNodeData: guard.originalNodeData
1177
+ fieldValues: { input: content, ...executionContext },
1178
+ // Envia contexto como fieldValues
1179
+ originalNodeData: guard.originalNodeData,
1180
+ $req: context?.$req,
1181
+ // Pass request context explicitly
1182
+ $vars: context?.$vars
1183
+ // Pass variables explicitly
1161
1184
  });
1162
1185
  if (result2 === false || typeof result2 === "object" && result2?.passed === false) {
1163
1186
  guardPassed = false;
1164
1187
  violationMessage = typeof result2?.message === "string" ? result2.message : `Fun\xE7\xE3o guardrail "${name}" reprovou o conte\xFAdo.`;
1188
+ if (actionInstruction) {
1189
+ violationMessage = actionInstruction;
1190
+ }
1165
1191
  } else if (typeof result2 === "object" && result2?.modifiedContent) {
1166
1192
  result2.modifiedContent = result2.modifiedContent;
1167
1193
  }
@@ -1172,15 +1198,41 @@ async function executeGuardrails(guardrails, content, mode = "fail-first") {
1172
1198
  }
1173
1199
  }
1174
1200
  } else if (guard.type === "model") {
1175
- const { model, evaluationPrompt, name } = guard;
1201
+ const { model, evaluationPrompt, name, actionInstruction } = guard;
1176
1202
  if (model && typeof model.invoke === "function") {
1177
1203
  try {
1178
- const prompt = evaluationPrompt.replace("{{content}}", content);
1204
+ let prompt = evaluationPrompt;
1205
+ if (actionInstruction) {
1206
+ prompt += `
1207
+
1208
+ INSTRU\xC7\xC3O ADICIONAL DE A\xC7\xC3O:
1209
+ ${actionInstruction}`;
1210
+ }
1211
+ if (prompt.includes("{{content}}")) {
1212
+ prompt = prompt.replace("{{content}}", content);
1213
+ } else {
1214
+ prompt = `${prompt}
1215
+
1216
+ CONTE\xDADO PARA AVALIAR:
1217
+ ${content}`;
1218
+ }
1179
1219
  const response = await model.invoke(prompt);
1180
1220
  const resultText = typeof response.content === "string" ? response.content : String(response.content);
1181
- if (resultText.toUpperCase().includes("UNSAFE")) {
1182
- guardPassed = false;
1183
- violationMessage = `Modelo de avalia\xE7\xE3o "${name}" detectou viola\xE7\xE3o de seguran\xE7a/pol\xEDtica.`;
1221
+ if (guard.action === "fix") {
1222
+ if (resultText && resultText.trim() !== content.trim() && !resultText.includes("SAFE")) {
1223
+ result.modifiedContent = resultText;
1224
+ violationMessage = `Conte\xFAdo reescrito pelo guardrail "${name}".`;
1225
+ result.violations.push({
1226
+ name: guard.name,
1227
+ message: violationMessage,
1228
+ action: "fix"
1229
+ });
1230
+ }
1231
+ } else {
1232
+ if (resultText.toUpperCase().includes("UNSAFE")) {
1233
+ guardPassed = false;
1234
+ violationMessage = actionInstruction || `Modelo de avalia\xE7\xE3o "${name}" detectou viola\xE7\xE3o de seguran\xE7a/pol\xEDtica.`;
1235
+ }
1184
1236
  }
1185
1237
  } catch (error) {
1186
1238
  console.error(`Error executing model guardrail "${name}":`, error);
@@ -1196,7 +1248,7 @@ async function executeGuardrails(guardrails, content, mode = "fail-first") {
1196
1248
  });
1197
1249
  if (guard.action === "block") {
1198
1250
  result.blocked = true;
1199
- result.message = violationMessage;
1251
+ result.message = `GUARDRAILS ATIVADO: ${violationMessage}`;
1200
1252
  if (mode === "fail-first") break;
1201
1253
  }
1202
1254
  }
@@ -1220,7 +1272,10 @@ GUARDRAIL [${guard.name}]: ${guard.prompt}`;
1220
1272
  var IaAgentNodeFunction = async (inputs) => {
1221
1273
  const { $field: _$field, $req: _$req, $inputs: _$inputs, $vars: _$vars } = inputs;
1222
1274
  const fieldValues = inputs.fieldValues || {};
1223
- const { model, tools, systemMessage, name, message, beforeGuardrails, afterGuardrails, guardrailMode } = fieldValues;
1275
+ const { model, tools, systemMessage, name, message, guardrails, guardrailMode } = fieldValues;
1276
+ const guardrailsList = Array.isArray(guardrails) ? guardrails : guardrails ? [guardrails] : [];
1277
+ const beforeGuardrails = guardrailsList.filter((g) => g?.phase === "before");
1278
+ const afterGuardrails = guardrailsList.filter((g) => !g?.phase || g?.phase === "after");
1224
1279
  const authToken = inputs.authToken;
1225
1280
  const stream = Boolean(inputs?.stream);
1226
1281
  const emitter = inputs?.emitter;
@@ -1231,8 +1286,8 @@ var IaAgentNodeFunction = async (inputs) => {
1231
1286
  throw new Error("Agent 'name' is required. Please provide a unique name for the agent in the node properties.");
1232
1287
  }
1233
1288
  const prepareGuardrails = async (list) => {
1234
- const guardrailsList = Array.isArray(list) ? list : [list];
1235
- return await Promise.all(guardrailsList.map(async (g) => {
1289
+ const guardrailsList2 = Array.isArray(list) ? list : [list];
1290
+ return await Promise.all(guardrailsList2.map(async (g) => {
1236
1291
  if (g?.type === "model" && g.model && !g.model.invoke) {
1237
1292
  if (!authToken) throw new Error("Auth token required for model guardrail");
1238
1293
  const modelInstance = await createLLMFromModel(g.model, authToken, false);
@@ -1241,9 +1296,12 @@ var IaAgentNodeFunction = async (inputs) => {
1241
1296
  return g;
1242
1297
  }));
1243
1298
  };
1299
+ let isBlocked = false;
1300
+ let guardrailViolations = [];
1244
1301
  if (message && beforeGuardrails) {
1245
1302
  const preparedBefore = await prepareGuardrails(beforeGuardrails);
1246
- const beforeResults = await executeGuardrails(preparedBefore, message, guardrailMode);
1303
+ const context = { ...inputs, input: message };
1304
+ const beforeResults = await executeGuardrails(preparedBefore, message, guardrailMode, context);
1247
1305
  if (beforeResults.blocked) {
1248
1306
  console.log(`\u{1F6E1}\uFE0F IaAgentNode "${name}": Blocked by before-agent guardrail:`, beforeResults.message);
1249
1307
  if (stream && emitter?.emitDelta) {
@@ -1256,9 +1314,9 @@ var IaAgentNodeFunction = async (inputs) => {
1256
1314
  }
1257
1315
  return {
1258
1316
  agent: null,
1259
- output: beforeResults.message || "Requisi\xE7\xE3o bloqueada por pol\xEDtica de seguran\xE7a.",
1317
+ output: beforeResults.message || "GUARDRAILS ATIVADO: Requisi\xE7\xE3o bloqueada por pol\xEDtica de seguran\xE7a.",
1260
1318
  blocked: true,
1261
- violations: beforeResults.violations
1319
+ violations: beforeResults.violations || []
1262
1320
  };
1263
1321
  }
1264
1322
  }
@@ -1278,17 +1336,65 @@ IMPORTANT: You must base your response on the last message in the conversation h
1278
1336
  finalSystemMessageContent = applyPromptGuardrails(finalSystemMessageContent, afterGuardrails);
1279
1337
  }
1280
1338
  const finalSystemMessage = new import_messages.SystemMessage(finalSystemMessageContent);
1339
+ const defaultModel = {
1340
+ model: "gemini-flash-latest",
1341
+ integrationId: "default-gemini"
1342
+ };
1343
+ const finalModel = model?.integrationId || typeof model?.bindTools === "function" ? model : defaultModel;
1344
+ console.log(`\u{1F916} IaAgentNode "${name}": Using model:`, finalModel === defaultModel ? "DEFAULT (Gemini)" : finalModel?.model || "instance");
1345
+ const tokenUsage = { input: 0, output: 0, total: 0 };
1346
+ const callbacks = [
1347
+ {
1348
+ handleLLMEnd: (output2) => {
1349
+ let usage = output2.llmOutput?.tokenUsage || output2.llmOutput?.estimatedTokenUsage;
1350
+ if (!usage && output2.generations && Array.isArray(output2.generations) && output2.generations.length > 0) {
1351
+ const firstGen = output2.generations[0][0];
1352
+ if (firstGen?.generationInfo?.tokenUsage) {
1353
+ usage = firstGen.generationInfo.tokenUsage;
1354
+ }
1355
+ }
1356
+ if (usage) {
1357
+ tokenUsage.input += usage.promptTokens || usage.input_tokens || 0;
1358
+ tokenUsage.output += usage.completionTokens || usage.output_tokens || 0;
1359
+ tokenUsage.total += usage.totalTokens || usage.total_tokens || 0;
1360
+ }
1361
+ }
1362
+ }
1363
+ ];
1364
+ if (stream && emitter) {
1365
+ callbacks.push({
1366
+ handleLLMNewToken: (token) => {
1367
+ if (emitter?.emitDelta) {
1368
+ emitter.emitDelta({
1369
+ content: token,
1370
+ actor: name,
1371
+ isAgent: true,
1372
+ isTool: false
1373
+ });
1374
+ }
1375
+ }
1376
+ });
1377
+ }
1281
1378
  let llmInstance;
1282
- if (model?.integrationId) {
1379
+ if (finalModel?.integrationId) {
1283
1380
  if (!authToken) {
1284
1381
  throw new Error("Auth token is required to instantiate LLM from integration");
1285
1382
  }
1286
- llmInstance = await createLLMFromModel(model, authToken, stream);
1287
- } else if (typeof model?.bindTools === "function") {
1288
- llmInstance = model;
1383
+ llmInstance = await createLLMFromModel(finalModel, authToken, stream);
1384
+ } else if (typeof finalModel?.bindTools === "function") {
1385
+ llmInstance = finalModel;
1289
1386
  } else {
1290
1387
  throw new Error("Invalid model: must have integrationId or be a valid LLM instance with bindTools method");
1291
1388
  }
1389
+ if (callbacks.length > 0) {
1390
+ if (llmInstance.callbacks) {
1391
+ if (Array.isArray(llmInstance.callbacks)) {
1392
+ llmInstance.callbacks.push(...callbacks);
1393
+ }
1394
+ } else {
1395
+ llmInstance.callbacks = callbacks;
1396
+ }
1397
+ }
1292
1398
  const agent = (0, import_prebuilt.createReactAgent)({
1293
1399
  llm: llmInstance,
1294
1400
  tools: toolsArray,
@@ -1305,14 +1411,17 @@ IMPORTANT: You must base your response on the last message in the conversation h
1305
1411
  let output = "";
1306
1412
  if (message) {
1307
1413
  try {
1308
- const invokeConfig = checkpointer ? { configurable: { thread_id: sessionId } } : {};
1414
+ const invokeConfig = {
1415
+ ...checkpointer ? { configurable: { thread_id: sessionId } } : {},
1416
+ callbacks
1417
+ // Also pass here as backup
1418
+ };
1309
1419
  if (stream && emitter) {
1310
1420
  const streamIterator = await agent.stream(
1311
1421
  { messages: [new import_messages.HumanMessage(message)] },
1312
1422
  invokeConfig
1313
1423
  );
1314
1424
  let lastMessages = [];
1315
- const sentContents = /* @__PURE__ */ new Set();
1316
1425
  for await (const step of streamIterator) {
1317
1426
  if (step && typeof step === "object") {
1318
1427
  for (const [key, value] of Object.entries(step)) {
@@ -1320,21 +1429,6 @@ IMPORTANT: You must base your response on the last message in the conversation h
1320
1429
  const messages = value.messages;
1321
1430
  if (Array.isArray(messages)) {
1322
1431
  lastMessages = messages;
1323
- for (const msg of messages) {
1324
- const content = msg?.content;
1325
- const contentStr = typeof content === "string" ? content : Array.isArray(content) ? content.map((p) => p.type === "text" ? p.text : "").filter(Boolean).join("") : "";
1326
- if (contentStr && !sentContents.has(contentStr)) {
1327
- sentContents.add(contentStr);
1328
- if (emitter?.emitDelta) {
1329
- emitter.emitDelta({
1330
- content: contentStr,
1331
- actor: name,
1332
- isAgent: true,
1333
- isTool: false
1334
- });
1335
- }
1336
- }
1337
- }
1338
1432
  }
1339
1433
  }
1340
1434
  }
@@ -1343,6 +1437,22 @@ IMPORTANT: You must base your response on the last message in the conversation h
1343
1437
  if (lastMessages.length > 0) {
1344
1438
  const lastMessage = lastMessages[lastMessages.length - 1];
1345
1439
  const content = lastMessage?.content;
1440
+ const msg = lastMessage;
1441
+ const usageMetadata = msg?.response_metadata?.tokenUsage || msg?.response_metadata?.usage || msg?.usage_metadata;
1442
+ if (usageMetadata) {
1443
+ const input = usageMetadata.promptTokens || usageMetadata.input_tokens || 0;
1444
+ const output2 = usageMetadata.completionTokens || usageMetadata.output_tokens || 0;
1445
+ const total = usageMetadata.totalTokens || usageMetadata.total_tokens || 0;
1446
+ if (tokenUsage.total === 0) {
1447
+ if (input + output2 > 0) {
1448
+ tokenUsage.input = input;
1449
+ tokenUsage.output = output2;
1450
+ tokenUsage.total = input + output2;
1451
+ } else if (total > 0) {
1452
+ tokenUsage.total = total;
1453
+ }
1454
+ }
1455
+ }
1346
1456
  if (typeof content === "string") {
1347
1457
  output = content;
1348
1458
  } else if (Array.isArray(content)) {
@@ -1361,6 +1471,22 @@ IMPORTANT: You must base your response on the last message in the conversation h
1361
1471
  if (result?.messages && result.messages.length > 0) {
1362
1472
  const lastMessage = result.messages[result.messages.length - 1];
1363
1473
  const content = lastMessage?.content;
1474
+ const msg = lastMessage;
1475
+ const usageMetadata = msg?.response_metadata?.tokenUsage || msg?.response_metadata?.usage || msg?.usage_metadata;
1476
+ if (usageMetadata) {
1477
+ const input = usageMetadata.promptTokens || usageMetadata.input_tokens || 0;
1478
+ const output2 = usageMetadata.completionTokens || usageMetadata.output_tokens || 0;
1479
+ const total = usageMetadata.totalTokens || usageMetadata.total_tokens || 0;
1480
+ if (tokenUsage.total === 0) {
1481
+ if (input + output2 > 0) {
1482
+ tokenUsage.input = input;
1483
+ tokenUsage.output = output2;
1484
+ tokenUsage.total = input + output2;
1485
+ } else if (total > 0) {
1486
+ tokenUsage.total = total;
1487
+ }
1488
+ }
1489
+ }
1364
1490
  if (typeof content === "string") {
1365
1491
  output = content;
1366
1492
  } else if (Array.isArray(content)) {
@@ -1376,22 +1502,42 @@ IMPORTANT: You must base your response on the last message in the conversation h
1376
1502
  }
1377
1503
  if (output && afterGuardrails) {
1378
1504
  const preparedAfter = await prepareGuardrails(afterGuardrails);
1379
- const afterResults = await executeGuardrails(preparedAfter, output, guardrailMode);
1505
+ const context = { ...inputs, input: output };
1506
+ const afterResults = await executeGuardrails(preparedAfter, output, guardrailMode, context);
1380
1507
  if (afterResults.blocked) {
1381
1508
  console.log(`\u{1F6E1}\uFE0F IaAgentNode "${name}": Response blocked by after-agent guardrail:`, afterResults.message);
1509
+ isBlocked = true;
1510
+ guardrailViolations = afterResults.violations || [];
1382
1511
  if (stream && emitter?.emitDelta) {
1383
1512
  emitter.emitDelta({
1384
1513
  content: `
1385
1514
 
1386
- \u26A0\uFE0F RESPOSTA BLOQUEADA: ${afterResults.message}`,
1515
+ ${afterResults.message}`,
1387
1516
  actor: name,
1388
1517
  isAgent: true,
1389
1518
  isError: true
1390
1519
  });
1391
1520
  }
1392
- output = afterResults.message || "Resposta bloqueada por pol\xEDtica de seguran\xE7a.";
1393
- } else if (afterResults.modifiedContent) {
1394
- output = afterResults.modifiedContent;
1521
+ output = afterResults.message || "GUARDRAILS ATIVADO: Resposta bloqueada por pol\xEDtica de seguran\xE7a.";
1522
+ } else {
1523
+ if (afterResults.modifiedContent) {
1524
+ output = afterResults.modifiedContent;
1525
+ }
1526
+ const warnings = afterResults.violations.filter((v) => v.action === "warn");
1527
+ if (warnings.length > 0) {
1528
+ const warningText = warnings.map((w) => `
1529
+
1530
+ \u26A0\uFE0F GUARDRAILS ATIVADO: ${w.message}`).join("");
1531
+ output += warningText;
1532
+ if (stream && emitter?.emitDelta) {
1533
+ emitter.emitDelta({
1534
+ content: warningText,
1535
+ actor: name,
1536
+ isAgent: true,
1537
+ isError: false
1538
+ });
1539
+ }
1540
+ }
1395
1541
  }
1396
1542
  }
1397
1543
  } catch (error) {
@@ -1399,9 +1545,19 @@ IMPORTANT: You must base your response on the last message in the conversation h
1399
1545
  output = `Error: ${error instanceof Error ? error.message : "Unknown error"}`;
1400
1546
  }
1401
1547
  }
1548
+ if (tokenUsage.total === 0 && (tokenUsage.input > 0 || tokenUsage.output > 0)) {
1549
+ tokenUsage.total = tokenUsage.input + tokenUsage.output;
1550
+ } else if (tokenUsage.total !== tokenUsage.input + tokenUsage.output) {
1551
+ tokenUsage.total = tokenUsage.input + tokenUsage.output;
1552
+ }
1553
+ console.log(`[TOKEN COUNT] Input: ${tokenUsage.input}, Output: ${tokenUsage.output}, Total: ${tokenUsage.total}`);
1402
1554
  return {
1403
1555
  agent,
1404
- output: output || ""
1556
+ response: output || "",
1557
+ output: output || "",
1558
+ // Keep both for safety
1559
+ blocked: isBlocked,
1560
+ violations: guardrailViolations
1405
1561
  };
1406
1562
  };
1407
1563
 
@@ -1821,7 +1977,7 @@ var import_langgraph_checkpoint_postgres = require("@langchain/langgraph-checkpo
1821
1977
  var PostgresMemoryNodeFunction = async (inputs) => {
1822
1978
  const { $field: _$field, $req: _$req, $inputs: _$inputs, $vars: _$vars } = inputs;
1823
1979
  const fieldValues = inputs.fieldValues || {};
1824
- const connectionString = fieldValues.connectionString || inputs.connectionString || "postgresql://postgres:postgres@localhost:5432/workflows";
1980
+ const connectionString = fieldValues.connectionString || inputs.connectionString || "postgresql://yugabyte:yugabyte@localhost:5433/workflows";
1825
1981
  try {
1826
1982
  const checkpointer = import_langgraph_checkpoint_postgres.PostgresSaver.fromConnString(connectionString);
1827
1983
  await checkpointer.setup();
@@ -2399,12 +2555,14 @@ var PromptGuardrailNode = {
2399
2555
 
2400
2556
  // src/nodes/guardrails/prompt/function.ts
2401
2557
  var PromptGuardrailNodeFunction = async (inputs) => {
2402
- const { fieldValues = {} } = inputs;
2403
- const { name, prompt } = fieldValues;
2558
+ const values = inputs.fieldValues || inputs;
2559
+ const { name, prompt } = values;
2404
2560
  return {
2405
- type: "prompt",
2406
- name: name || "Prompt Guardrail",
2407
- prompt: prompt || ""
2561
+ guardrail: {
2562
+ type: "prompt",
2563
+ name: name || "Prompt Guardrail",
2564
+ prompt: prompt || ""
2565
+ }
2408
2566
  };
2409
2567
  };
2410
2568
 
@@ -2415,7 +2573,8 @@ var RuleGuardrailNodeSchema = import_zod14.z.object({
2415
2573
  phase: import_zod14.z.enum(["before", "after"]).describe("Fase de execu\xE7\xE3o"),
2416
2574
  ruleType: import_zod14.z.enum(["maxValue", "minValue", "regex", "keywords", "pii"]).describe("Tipo de regra"),
2417
2575
  config: import_zod14.z.any().describe("Configura\xE7\xE3o da regra"),
2418
- action: import_zod14.z.enum(["block", "warn", "modify"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o")
2576
+ action: import_zod14.z.enum(["block", "warn", "modify"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o"),
2577
+ actionInstruction: import_zod14.z.string().optional().describe("Instru\xE7\xE3o adicional para a a\xE7\xE3o")
2419
2578
  });
2420
2579
  var RuleGuardrailNode = {
2421
2580
  label: "Rule Guardrail",
@@ -2479,6 +2638,13 @@ var RuleGuardrailNode = {
2479
2638
  { label: "Modificar/Ocultar", value: "modify" }
2480
2639
  ]
2481
2640
  },
2641
+ {
2642
+ id: "actionInstruction",
2643
+ label: "Instru\xE7\xE3o da A\xE7\xE3o",
2644
+ type: "textarea",
2645
+ required: false,
2646
+ placeholder: "Ex: Bloquear: 'N\xE3o posso falar sobre isso'. Warn: 'Aten\xE7\xE3o...'"
2647
+ },
2482
2648
  {
2483
2649
  id: "guardrail",
2484
2650
  label: "Guardrail",
@@ -2497,15 +2663,21 @@ var RuleGuardrailNode = {
2497
2663
 
2498
2664
  // src/nodes/guardrails/rule/function.ts
2499
2665
  var RuleGuardrailNodeFunction = async (inputs) => {
2500
- const { fieldValues = {} } = inputs;
2501
- const { name, phase, ruleType, config, action } = fieldValues;
2666
+ const values = inputs.fieldValues || inputs;
2667
+ const {
2668
+ name,
2669
+ ruleType,
2670
+ config,
2671
+ action
2672
+ } = values;
2502
2673
  return {
2503
- type: "rule",
2504
- name: name || "Rule Guardrail",
2505
- phase: phase || "after",
2506
- ruleType: ruleType || "keywords",
2507
- config: config || "",
2508
- action: action || "block"
2674
+ guardrail: {
2675
+ type: "rule",
2676
+ name: name || "Rule Guardrail",
2677
+ ruleType: ruleType || "keywords",
2678
+ config: config || "",
2679
+ action: action || "block"
2680
+ }
2509
2681
  };
2510
2682
  };
2511
2683
 
@@ -2515,7 +2687,8 @@ var FunctionGuardrailNodeSchema = import_zod15.z.object({
2515
2687
  name: import_zod15.z.string().describe("Nome do guardrail"),
2516
2688
  phase: import_zod15.z.enum(["before", "after"]).describe("Fase de execu\xE7\xE3o"),
2517
2689
  description: import_zod15.z.string().optional().describe("Descri\xE7\xE3o do que a fun\xE7\xE3o valida"),
2518
- action: import_zod15.z.enum(["block", "warn", "modify", "escalate"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o")
2690
+ action: import_zod15.z.enum(["block", "warn", "modify", "escalate"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o"),
2691
+ actionInstruction: import_zod15.z.string().optional().describe("Instru\xE7\xE3o adicional para a a\xE7\xE3o")
2519
2692
  });
2520
2693
  var FunctionGuardrailNode = {
2521
2694
  label: "Function Guardrail",
@@ -2582,6 +2755,13 @@ var FunctionGuardrailNode = {
2582
2755
  { label: "Escalar (Human-in-the-loop)", value: "escalate" }
2583
2756
  ]
2584
2757
  },
2758
+ {
2759
+ id: "actionInstruction",
2760
+ label: "Instru\xE7\xE3o da A\xE7\xE3o",
2761
+ type: "textarea",
2762
+ required: false,
2763
+ placeholder: "Ex: Instru\xE7\xE3o para a modifica\xE7\xE3o ou mensagem de bloqueio"
2764
+ },
2585
2765
  {
2586
2766
  id: "guardrail",
2587
2767
  label: "Guardrail",
@@ -2600,26 +2780,24 @@ var FunctionGuardrailNode = {
2600
2780
 
2601
2781
  // src/nodes/guardrails/function/function.ts
2602
2782
  var FunctionGuardrailNodeFunction = async (inputs) => {
2603
- const { fieldValues = {} } = inputs;
2783
+ const values = inputs.fieldValues || inputs;
2604
2784
  const {
2605
2785
  name,
2606
- phase,
2607
2786
  description,
2608
2787
  action,
2609
2788
  nodeFunction,
2610
- nodeType,
2611
2789
  originalNodeData
2612
- } = fieldValues;
2790
+ } = values;
2613
2791
  return {
2614
- type: "function",
2615
- name: name || "Function Guardrail",
2616
- phase: phase || "after",
2617
- description: description || "",
2618
- action: action || "block",
2619
- // Injected by executeWorkflow.ts
2620
- nodeFunction,
2621
- nodeType,
2622
- originalNodeData
2792
+ guardrail: {
2793
+ type: "function",
2794
+ name: name || "Function Guardrail",
2795
+ description,
2796
+ action: action || "block",
2797
+ // Injected by executeWorkflow.ts
2798
+ nodeFunction,
2799
+ originalNodeData
2800
+ }
2623
2801
  };
2624
2802
  };
2625
2803
 
@@ -2629,7 +2807,9 @@ var ModelGuardrailNodeSchema = import_zod16.z.object({
2629
2807
  name: import_zod16.z.string().describe("Nome do guardrail"),
2630
2808
  evaluationPrompt: import_zod16.z.string().describe("Prompt de avalia\xE7\xE3o"),
2631
2809
  model: import_zod16.z.any().describe("Modelo LLM para avalia\xE7\xE3o"),
2632
- action: import_zod16.z.enum(["block", "warn", "escalate"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o")
2810
+ action: import_zod16.z.enum(["block", "warn", "fix", "escalate"]).describe("A\xE7\xE3o em caso de viola\xE7\xE3o"),
2811
+ phase: import_zod16.z.enum(["before", "after"]).describe("Fase de execu\xE7\xE3o"),
2812
+ actionInstruction: import_zod16.z.string().optional().describe("Instru\xE7\xE3o adicional para a a\xE7\xE3o")
2633
2813
  });
2634
2814
  var ModelGuardrailNode = {
2635
2815
  label: "Model Guardrail",
@@ -2680,10 +2860,29 @@ var ModelGuardrailNode = {
2680
2860
  defaultValue: "block",
2681
2861
  options: [
2682
2862
  { label: "Bloquear Resposta", value: "block" },
2863
+ { label: "Corrigir/Reescrever (Fix)", value: "fix" },
2683
2864
  { label: "Avisar (Warning)", value: "warn" },
2684
2865
  { label: "Escalar (Human-in-the-loop)", value: "escalate" }
2685
2866
  ]
2686
2867
  },
2868
+ {
2869
+ id: "actionInstruction",
2870
+ label: "Instru\xE7\xE3o da A\xE7\xE3o",
2871
+ type: "textarea",
2872
+ required: false,
2873
+ placeholder: "Ex: Se bloquear, diga 'Pol\xEDtica violada'. Se corrigir, 'Reescreva com...'"
2874
+ },
2875
+ {
2876
+ id: "phase",
2877
+ label: "Fase de Execu\xE7\xE3o",
2878
+ type: "select",
2879
+ required: true,
2880
+ defaultValue: "after",
2881
+ options: [
2882
+ { label: "Antes do Agente (Input)", value: "before" },
2883
+ { label: "Depois do Agente (Output)", value: "after" }
2884
+ ]
2885
+ },
2687
2886
  {
2688
2887
  id: "guardrail",
2689
2888
  label: "Guardrail",
@@ -2702,19 +2901,25 @@ var ModelGuardrailNode = {
2702
2901
 
2703
2902
  // src/nodes/guardrails/model/function.ts
2704
2903
  var ModelGuardrailNodeFunction = async (inputs) => {
2705
- const { fieldValues = {} } = inputs;
2904
+ const values = inputs.fieldValues || inputs;
2706
2905
  const {
2707
2906
  name,
2708
2907
  evaluationPrompt,
2709
2908
  model,
2710
2909
  action
2711
- } = fieldValues;
2910
+ } = values;
2911
+ const defaultModel = {
2912
+ model: "gemini-flash-latest",
2913
+ integrationId: "default-gemini"
2914
+ };
2712
2915
  return {
2713
- type: "model",
2714
- name: name || "Model Guardrail",
2715
- evaluationPrompt: evaluationPrompt || "Avalie se este conte\xFAdo \xE9 seguro. Responda apenas SAFE ou UNSAFE.",
2716
- model,
2717
- action: action || "block"
2916
+ guardrail: {
2917
+ type: "model",
2918
+ name: name || "Model Guardrail",
2919
+ evaluationPrompt: evaluationPrompt || "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}}",
2920
+ model: model || defaultModel,
2921
+ action: action || "block"
2922
+ }
2718
2923
  };
2719
2924
  };
2720
2925