@n8n/ai-workflow-builder 0.27.1 → 0.28.0

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.
Files changed (66) hide show
  1. package/dist/build.tsbuildinfo +1 -1
  2. package/dist/chains/prompts/parameter-types/system-message.d.ts +1 -0
  3. package/dist/chains/prompts/parameter-types/system-message.js +75 -0
  4. package/dist/chains/prompts/parameter-types/system-message.js.map +1 -0
  5. package/dist/chains/prompts/prompt-builder.d.ts +1 -0
  6. package/dist/chains/prompts/prompt-builder.js +23 -1
  7. package/dist/chains/prompts/prompt-builder.js.map +1 -1
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/tools/builder-tools.js +3 -0
  12. package/dist/tools/builder-tools.js.map +1 -1
  13. package/dist/tools/prompts/main-agent.prompt.js +93 -0
  14. package/dist/tools/prompts/main-agent.prompt.js.map +1 -1
  15. package/dist/tools/validate-workflow.tool.d.ts +5 -0
  16. package/dist/tools/validate-workflow.tool.js +77 -0
  17. package/dist/tools/validate-workflow.tool.js.map +1 -0
  18. package/dist/utils/operations-processor.d.ts +2 -0
  19. package/dist/utils/operations-processor.js +1 -0
  20. package/dist/utils/operations-processor.js.map +1 -1
  21. package/dist/utils/stream-processor.d.ts +1 -0
  22. package/dist/utils/stream-processor.js +14 -1
  23. package/dist/utils/stream-processor.js.map +1 -1
  24. package/dist/utils/workflow-validation.d.ts +2 -0
  25. package/dist/utils/workflow-validation.js +36 -0
  26. package/dist/utils/workflow-validation.js.map +1 -0
  27. package/dist/validation/checks/agent-prompt.d.ts +3 -0
  28. package/dist/validation/checks/agent-prompt.js +45 -0
  29. package/dist/validation/checks/agent-prompt.js.map +1 -0
  30. package/dist/validation/checks/connections.d.ts +4 -0
  31. package/dist/validation/checks/connections.js +131 -0
  32. package/dist/validation/checks/connections.js.map +1 -0
  33. package/dist/validation/checks/from-ai.d.ts +4 -0
  34. package/dist/validation/checks/from-ai.js +59 -0
  35. package/dist/validation/checks/from-ai.js.map +1 -0
  36. package/dist/validation/checks/index.d.ts +5 -0
  37. package/dist/validation/checks/index.js +14 -0
  38. package/dist/validation/checks/index.js.map +1 -0
  39. package/dist/validation/checks/tools.d.ts +4 -0
  40. package/dist/validation/checks/tools.js +44 -0
  41. package/dist/validation/checks/tools.js.map +1 -0
  42. package/dist/validation/checks/trigger.d.ts +8 -0
  43. package/dist/validation/checks/trigger.js +35 -0
  44. package/dist/validation/checks/trigger.js.map +1 -0
  45. package/dist/validation/programmatic.d.ts +3 -0
  46. package/dist/validation/programmatic.js +20 -0
  47. package/dist/validation/programmatic.js.map +1 -0
  48. package/dist/validation/types.d.ts +41 -0
  49. package/dist/validation/types.js +3 -0
  50. package/dist/validation/types.js.map +1 -0
  51. package/dist/validation/utils/expressions.d.ts +3 -0
  52. package/dist/validation/utils/expressions.js +37 -0
  53. package/dist/validation/utils/expressions.js.map +1 -0
  54. package/dist/validation/utils/is-tool.d.ts +2 -0
  55. package/dist/validation/utils/is-tool.js +7 -0
  56. package/dist/validation/utils/is-tool.js.map +1 -0
  57. package/dist/validation/utils/resolve-connections.d.ts +8 -0
  58. package/dist/validation/utils/resolve-connections.js +64 -0
  59. package/dist/validation/utils/resolve-connections.js.map +1 -0
  60. package/dist/workflow-builder-agent.d.ts +2 -0
  61. package/dist/workflow-builder-agent.js +28 -25
  62. package/dist/workflow-builder-agent.js.map +1 -1
  63. package/dist/workflow-state.d.ts +2 -0
  64. package/dist/workflow-state.js +4 -0
  65. package/dist/workflow-state.js.map +1 -1
  66. package/package.json +10 -9
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateAgentPrompt = validateAgentPrompt;
4
+ const expressions_1 = require("../utils/expressions");
5
+ function isOptionsWithSystemMessage(value) {
6
+ return (typeof value === 'object' &&
7
+ value !== null &&
8
+ !Array.isArray(value) &&
9
+ ('systemMessage' in value || Object.keys(value).length === 0));
10
+ }
11
+ function validateAgentPrompt(workflow) {
12
+ const violations = [];
13
+ if (!workflow.nodes || workflow.nodes.length === 0) {
14
+ return [];
15
+ }
16
+ for (const node of workflow.nodes) {
17
+ if (node.type === '@n8n/n8n-nodes-langchain.agent') {
18
+ const textParam = node.parameters?.text;
19
+ const promptType = node.parameters?.promptType;
20
+ const options = node.parameters?.options;
21
+ let systemMessage;
22
+ if (isOptionsWithSystemMessage(options)) {
23
+ systemMessage = options.systemMessage;
24
+ }
25
+ if (promptType !== 'auto') {
26
+ if (!textParam || !(0, expressions_1.containsExpression)(textParam)) {
27
+ violations.push({
28
+ type: 'major',
29
+ description: `Agent node "${node.name}" has no expression in its prompt field. This likely means it failed to use chatInput or dynamic context`,
30
+ pointsDeducted: 20,
31
+ });
32
+ }
33
+ if (!systemMessage || systemMessage.trim().length === 0) {
34
+ violations.push({
35
+ type: 'major',
36
+ description: `Agent node "${node.name}" has no system message. System-level instructions (role, tasks, behavior) should be in the system message field, not the text field`,
37
+ pointsDeducted: 25,
38
+ });
39
+ }
40
+ }
41
+ }
42
+ }
43
+ return violations;
44
+ }
45
+ //# sourceMappingURL=agent-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-prompt.js","sourceRoot":"","sources":["../../../src/validation/checks/agent-prompt.ts"],"names":[],"mappings":";;AA4BA,kDAiDC;AAxED,sDAA0D;AAK1D,SAAS,0BAA0B,CAClC,KAAc;IAEd,OAAO,CACN,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACrB,CAAC,eAAe,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAC7D,CAAC;AACH,CAAC;AASD,SAAgB,mBAAmB,CAAC,QAAwB;IAC3D,MAAM,UAAU,GAA4B,EAAE,CAAC;IAG/C,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,CAAC;IACX,CAAC;IAGD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEnC,IAAI,IAAI,CAAC,IAAI,KAAK,gCAAgC,EAAE,CAAC;YAEpD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC;YACxC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;YAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC;YAGzC,IAAI,aAAiC,CAAC;YACtC,IAAI,0BAA0B,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;YACvC,CAAC;YAID,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;gBAE3B,IAAI,CAAC,SAAS,IAAI,CAAC,IAAA,gCAAkB,EAAC,SAAS,CAAC,EAAE,CAAC;oBAClD,UAAU,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,OAAO;wBACb,WAAW,EAAE,eAAe,IAAI,CAAC,IAAI,0GAA0G;wBAC/I,cAAc,EAAE,EAAE;qBAClB,CAAC,CAAC;gBACJ,CAAC;gBAID,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACzD,UAAU,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,OAAO;wBACb,WAAW,EAAE,eAAe,IAAI,CAAC,IAAI,sIAAsI;wBAC3K,cAAc,EAAE,EAAE;qBAClB,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { INodeTypeDescription } from 'n8n-workflow';
2
+ import type { SimpleWorkflow } from '../../types';
3
+ import type { ProgrammaticViolation } from '../types';
4
+ export declare function validateConnections(workflow: SimpleWorkflow, nodeTypes: INodeTypeDescription[]): ProgrammaticViolation[];
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateConnections = validateConnections;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const resolve_connections_1 = require("../../validation/utils/resolve-connections");
6
+ function getProvidedInputTypes(nodeConnections) {
7
+ const providedInputTypes = new Map();
8
+ if (!nodeConnections)
9
+ return providedInputTypes;
10
+ for (const [connectionType, connections] of Object.entries(nodeConnections)) {
11
+ let totalConnections = 0;
12
+ for (const connectionSet of connections) {
13
+ if (!connectionSet)
14
+ continue;
15
+ totalConnections += connectionSet.length;
16
+ }
17
+ if (totalConnections > 0) {
18
+ providedInputTypes.set(connectionType, totalConnections);
19
+ }
20
+ }
21
+ return providedInputTypes;
22
+ }
23
+ function checkMissingRequiredInputs(nodeInfo, providedInputTypes) {
24
+ const issues = [];
25
+ if (!nodeInfo.resolvedInputs)
26
+ return issues;
27
+ for (const input of nodeInfo.resolvedInputs) {
28
+ const providedCount = providedInputTypes.get(input.type) ?? 0;
29
+ if (input.required && providedCount === 0) {
30
+ issues.push({
31
+ type: 'critical',
32
+ description: `Node ${nodeInfo.node.name} (${nodeInfo.node.type}) is missing required input of type ${input.type}`,
33
+ pointsDeducted: 50,
34
+ });
35
+ }
36
+ }
37
+ return issues;
38
+ }
39
+ function checkUnsupportedConnections(nodeInfo, providedInputTypes) {
40
+ const issues = [];
41
+ if (!nodeInfo.resolvedInputs)
42
+ return issues;
43
+ const supportedTypes = new Set(nodeInfo.resolvedInputs.map((input) => input.type));
44
+ for (const [type] of providedInputTypes) {
45
+ if (!supportedTypes.has(type)) {
46
+ issues.push({
47
+ type: 'critical',
48
+ description: `Node ${nodeInfo.node.name} (${nodeInfo.node.type}) received unsupported connection type ${type}`,
49
+ pointsDeducted: 50,
50
+ });
51
+ }
52
+ }
53
+ return issues;
54
+ }
55
+ function checkMergeNodeConnections(nodeInfo, nodeConnections) {
56
+ const issues = [];
57
+ if (/\.merge$/.test(nodeInfo.node.type)) {
58
+ const providedInputTypes = getProvidedInputTypes(nodeConnections);
59
+ const totalInputConnections = providedInputTypes.get('main') ?? 0;
60
+ if (totalInputConnections < 2) {
61
+ issues.push({
62
+ type: 'major',
63
+ description: `Merge node ${nodeInfo.node.name} has only ${totalInputConnections} input connection(s). Merge nodes require at least 2 inputs to function properly.`,
64
+ pointsDeducted: 20,
65
+ });
66
+ }
67
+ const expectedInputs = nodeInfo.resolvedInputs?.filter((input) => input.type === 'main').length ?? 1;
68
+ if (totalInputConnections !== expectedInputs) {
69
+ issues.push({
70
+ type: 'minor',
71
+ description: `Merge node ${nodeInfo.node.name} has ${totalInputConnections} input connections but is configured to accept ${expectedInputs}.`,
72
+ pointsDeducted: 10,
73
+ });
74
+ }
75
+ const mainConnections = nodeConnections?.main ?? [];
76
+ const missingIndexes = [];
77
+ for (let inputIndex = 0; inputIndex < expectedInputs; inputIndex++) {
78
+ const connectionsForIndex = mainConnections[inputIndex];
79
+ const hasConnections = Array.isArray(connectionsForIndex) && connectionsForIndex.length > 0;
80
+ if (!hasConnections) {
81
+ missingIndexes.push(inputIndex + 1);
82
+ }
83
+ }
84
+ if (missingIndexes.length > 0) {
85
+ issues.push({
86
+ type: 'major',
87
+ description: `Merge node ${nodeInfo.node.name} is missing connections for input(s) ${missingIndexes.join(', ')}.`,
88
+ pointsDeducted: 20,
89
+ });
90
+ }
91
+ }
92
+ return issues;
93
+ }
94
+ function validateConnections(workflow, nodeTypes) {
95
+ const violations = [];
96
+ if (!workflow.connections) {
97
+ workflow.connections = {};
98
+ }
99
+ const connectionsByDestination = (0, n8n_workflow_1.mapConnectionsByDestination)(workflow.connections);
100
+ for (const node of workflow.nodes) {
101
+ const nodeType = nodeTypes.find((type) => type.name === node.type);
102
+ if (!nodeType) {
103
+ violations.push({
104
+ type: 'critical',
105
+ description: `Node type ${node.type} not found for node ${node.name}`,
106
+ pointsDeducted: 50,
107
+ });
108
+ continue;
109
+ }
110
+ const nodeInfo = { node, nodeType };
111
+ try {
112
+ nodeInfo.resolvedInputs = (0, resolve_connections_1.resolveNodeInputs)(nodeInfo);
113
+ nodeInfo.resolvedOutputs = (0, resolve_connections_1.resolveNodeOutputs)(nodeInfo);
114
+ }
115
+ catch (error) {
116
+ violations.push({
117
+ type: 'critical',
118
+ description: `Failed to resolve connections for node ${node.name} (${node.type}): ${error instanceof Error ? error.message : String(error)}`,
119
+ pointsDeducted: 50,
120
+ });
121
+ continue;
122
+ }
123
+ const nodeConnections = connectionsByDestination[node.name];
124
+ const providedInputTypes = getProvidedInputTypes(nodeConnections);
125
+ violations.push(...checkMissingRequiredInputs(nodeInfo, providedInputTypes));
126
+ violations.push(...checkUnsupportedConnections(nodeInfo, providedInputTypes));
127
+ violations.push(...checkMergeNodeConnections(nodeInfo, nodeConnections));
128
+ }
129
+ return violations;
130
+ }
131
+ //# sourceMappingURL=connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connections.js","sourceRoot":"","sources":["../../../src/validation/checks/connections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { INodeTypeDescription } from 'n8n-workflow';
2
+ import type { SimpleWorkflow } from '../../types';
3
+ import type { ProgrammaticViolation } from '../types';
4
+ export declare function validateFromAi(workflow: SimpleWorkflow, nodeTypes: INodeTypeDescription[]): ProgrammaticViolation[];
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateFromAi = validateFromAi;
4
+ const is_tool_1 = require("../utils/is-tool");
5
+ function containsFromAi(value) {
6
+ if (typeof value !== 'string') {
7
+ return false;
8
+ }
9
+ return /\$from[Aa][Ii]\(.+\)/.test(value);
10
+ }
11
+ function parametersContainFromAi(parameters) {
12
+ for (const value of Object.values(parameters)) {
13
+ if (containsFromAi(value)) {
14
+ return true;
15
+ }
16
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
17
+ if (parametersContainFromAi(value)) {
18
+ return true;
19
+ }
20
+ }
21
+ if (Array.isArray(value)) {
22
+ for (const item of value) {
23
+ if (containsFromAi(item)) {
24
+ return true;
25
+ }
26
+ if (item && typeof item === 'object' && !Array.isArray(value)) {
27
+ if (parametersContainFromAi(value)) {
28
+ return true;
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ return false;
35
+ }
36
+ function validateFromAi(workflow, nodeTypes) {
37
+ const violations = [];
38
+ if (!workflow.nodes || workflow.nodes.length === 0) {
39
+ return violations;
40
+ }
41
+ for (const node of workflow.nodes) {
42
+ const nodeType = nodeTypes.find((type) => type.name === node.type);
43
+ if (!nodeType) {
44
+ continue;
45
+ }
46
+ if ((0, is_tool_1.isTool)(nodeType)) {
47
+ continue;
48
+ }
49
+ if (node.parameters && parametersContainFromAi(node.parameters)) {
50
+ violations.push({
51
+ type: 'major',
52
+ description: `Non-tool node "${node.name}" (${node.type}) uses $fromAI in its parameters. $fromAI is only for tool nodes connected to AI agents.`,
53
+ pointsDeducted: 20,
54
+ });
55
+ }
56
+ }
57
+ return violations;
58
+ }
59
+ //# sourceMappingURL=from-ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"from-ai.js","sourceRoot":"","sources":["../../../src/validation/checks/from-ai.ts"],"names":[],"mappings":";;AA6CA,wCA8BC;AAtED,8CAA0C;AAE1C,SAAS,cAAc,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,uBAAuB,CAAC,UAA2B;IAC3D,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjE,IAAI,uBAAuB,CAAC,KAAwB,CAAC,EAAE,CAAC;gBACvD,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1B,OAAO,IAAI,CAAC;gBACb,CAAC;gBAED,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/D,IAAI,uBAAuB,CAAC,KAAwB,CAAC,EAAE,CAAC;wBACvD,OAAO,IAAI,CAAC;oBACb,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAgB,cAAc,CAC7B,QAAwB,EACxB,SAAiC;IAEjC,MAAM,UAAU,GAA4B,EAAE,CAAC;IAE/C,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,SAAS;QACV,CAAC;QAED,IAAI,IAAA,gBAAM,EAAC,QAAQ,CAAC,EAAE,CAAC;YACtB,SAAS;QACV,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,IAAI,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACjE,UAAU,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,kBAAkB,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,0FAA0F;gBACjJ,cAAc,EAAE,EAAE;aAClB,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { validateAgentPrompt } from './agent-prompt';
2
+ export { validateConnections } from './connections';
3
+ export { validateFromAi } from './from-ai';
4
+ export { validateTools } from './tools';
5
+ export { validateTrigger, type TriggerEvaluationResult, } from './trigger';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateTrigger = exports.validateTools = exports.validateFromAi = exports.validateConnections = exports.validateAgentPrompt = void 0;
4
+ var agent_prompt_1 = require("./agent-prompt");
5
+ Object.defineProperty(exports, "validateAgentPrompt", { enumerable: true, get: function () { return agent_prompt_1.validateAgentPrompt; } });
6
+ var connections_1 = require("./connections");
7
+ Object.defineProperty(exports, "validateConnections", { enumerable: true, get: function () { return connections_1.validateConnections; } });
8
+ var from_ai_1 = require("./from-ai");
9
+ Object.defineProperty(exports, "validateFromAi", { enumerable: true, get: function () { return from_ai_1.validateFromAi; } });
10
+ var tools_1 = require("./tools");
11
+ Object.defineProperty(exports, "validateTools", { enumerable: true, get: function () { return tools_1.validateTools; } });
12
+ var trigger_1 = require("./trigger");
13
+ Object.defineProperty(exports, "validateTrigger", { enumerable: true, get: function () { return trigger_1.validateTrigger; } });
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/validation/checks/index.ts"],"names":[],"mappings":";;;AAAA,+CAAqD;AAA5C,mHAAA,mBAAmB,OAAA;AAC5B,6CAAoD;AAA3C,kHAAA,mBAAmB,OAAA;AAC5B,qCAA2C;AAAlC,yGAAA,cAAc,OAAA;AACvB,iCAAwC;AAA/B,sGAAA,aAAa,OAAA;AACtB,qCAGmB;AAFlB,0GAAA,eAAe,OAAA"}
@@ -0,0 +1,4 @@
1
+ import type { INodeTypeDescription } from 'n8n-workflow';
2
+ import type { SimpleWorkflow } from '../../types';
3
+ import type { SingleEvaluatorResult } from '../types';
4
+ export declare function validateTools(workflow: SimpleWorkflow, nodeTypes: INodeTypeDescription[]): SingleEvaluatorResult['violations'];
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateTools = validateTools;
4
+ const expressions_1 = require("../utils/expressions");
5
+ const is_tool_1 = require("../utils/is-tool");
6
+ const toolsWithoutParameters = [
7
+ '@n8n/n8n-nodes-langchain.toolCalculator',
8
+ '@n8n/n8n-nodes-langchain.toolVectorStore',
9
+ '@n8n/n8n-nodes-langchain.vectorStoreInMemory',
10
+ '@n8n/n8n-nodes-langchain.mcpClientTool',
11
+ '@n8n/n8n-nodes-langchain.toolWikipedia',
12
+ '@n8n/n8n-nodes-langchain.toolSerpApi',
13
+ ];
14
+ function validateTools(workflow, nodeTypes) {
15
+ const violations = [];
16
+ if (!workflow.nodes || workflow.nodes.length === 0) {
17
+ return violations;
18
+ }
19
+ for (const node of workflow.nodes) {
20
+ const nodeType = nodeTypes.find((type) => type.name === node.type);
21
+ if (!nodeType) {
22
+ continue;
23
+ }
24
+ if ((0, is_tool_1.isTool)(nodeType) && !toolsWithoutParameters.includes(node.type)) {
25
+ if (!node.parameters || Object.keys(node.parameters).length === 0) {
26
+ violations.push({
27
+ type: 'major',
28
+ description: `Tool node "${node.name}" has no parameters set.`,
29
+ pointsDeducted: 20,
30
+ });
31
+ continue;
32
+ }
33
+ if (!(0, expressions_1.nodeParametersContainExpression)(node.parameters)) {
34
+ violations.push({
35
+ type: 'major',
36
+ description: `Tool node "${node.name}" has no expressions in its parameters. This likely means it is not using dynamic input.`,
37
+ pointsDeducted: 20,
38
+ });
39
+ }
40
+ }
41
+ }
42
+ return violations;
43
+ }
44
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/validation/checks/tools.ts"],"names":[],"mappings":";;AAiBA,sCAqCC;AAjDD,sDAAuE;AACvE,8CAA0C;AAE1C,MAAM,sBAAsB,GAAG;IAC9B,yCAAyC;IACzC,0CAA0C;IAC1C,8CAA8C;IAC9C,wCAAwC;IACxC,wCAAwC;IACxC,sCAAsC;CACtC,CAAC;AAEF,SAAgB,aAAa,CAC5B,QAAwB,EACxB,SAAiC;IAEjC,MAAM,UAAU,GAAwC,EAAE,CAAC;IAE3D,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,SAAS;QACV,CAAC;QAED,IAAI,IAAA,gBAAM,EAAC,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACrE,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnE,UAAU,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,cAAc,IAAI,CAAC,IAAI,0BAA0B;oBAC9D,cAAc,EAAE,EAAE;iBAClB,CAAC,CAAC;gBACH,SAAS;YACV,CAAC;YAED,IAAI,CAAC,IAAA,6CAA+B,EAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACvD,UAAU,CAAC,IAAI,CAAC;oBACf,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,cAAc,IAAI,CAAC,IAAI,0FAA0F;oBAC9H,cAAc,EAAE,EAAE;iBAClB,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { INodeTypeDescription } from 'n8n-workflow';
2
+ import type { SimpleWorkflow } from '../../types';
3
+ import type { ProgrammaticViolation, SingleEvaluatorResult } from '../types';
4
+ export interface TriggerEvaluationResult extends SingleEvaluatorResult {
5
+ hasTrigger: boolean;
6
+ triggerNodes: string[];
7
+ }
8
+ export declare function validateTrigger(workflow: SimpleWorkflow, nodeTypes: INodeTypeDescription[]): ProgrammaticViolation[];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateTrigger = validateTrigger;
4
+ const isTriggerNode = (nodeType) => nodeType.group.includes('trigger');
5
+ function validateTrigger(workflow, nodeTypes) {
6
+ const violations = [];
7
+ const triggerNodes = [];
8
+ if (!workflow.nodes || workflow.nodes.length === 0) {
9
+ violations.push({
10
+ type: 'critical',
11
+ description: 'Workflow has no nodes',
12
+ pointsDeducted: 50,
13
+ });
14
+ return violations;
15
+ }
16
+ for (const node of workflow.nodes) {
17
+ const nodeType = nodeTypes.find((type) => type.name === node.type);
18
+ if (!nodeType) {
19
+ continue;
20
+ }
21
+ if (isTriggerNode(nodeType)) {
22
+ triggerNodes.push(node.name);
23
+ }
24
+ }
25
+ const hasTrigger = triggerNodes.length > 0;
26
+ if (!hasTrigger) {
27
+ violations.push({
28
+ type: 'critical',
29
+ description: 'Workflow must have at least one trigger node to start execution',
30
+ pointsDeducted: 50,
31
+ });
32
+ }
33
+ return violations;
34
+ }
35
+ //# sourceMappingURL=trigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../../src/validation/checks/trigger.ts"],"names":[],"mappings":";;AAaA,0CAwCC;AA1CD,MAAM,aAAa,GAAG,CAAC,QAA8B,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAE7F,SAAgB,eAAe,CAC9B,QAAwB,EACxB,SAAiC;IAEjC,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,UAAU,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,uBAAuB;YACpC,cAAc,EAAE,EAAE;SAClB,CAAC,CAAC;QAEH,OAAO,UAAU,CAAC;IACnB,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,SAAS;QACV,CAAC;QAED,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;IACF,CAAC;IAED,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IAE3C,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,UAAU,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,iEAAiE;YAC9E,cAAc,EAAE,EAAE;SAClB,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { INodeTypeDescription } from 'n8n-workflow';
2
+ import type { ProgrammaticChecksResult, ProgrammaticEvaluationInput } from './types';
3
+ export declare function programmaticValidation(input: ProgrammaticEvaluationInput, nodeTypes: INodeTypeDescription[]): ProgrammaticChecksResult;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.programmaticValidation = programmaticValidation;
4
+ const checks_1 = require("../validation/checks");
5
+ function programmaticValidation(input, nodeTypes) {
6
+ const { generatedWorkflow } = input;
7
+ const connectionsValidationResult = (0, checks_1.validateConnections)(generatedWorkflow, nodeTypes);
8
+ const triggerValidationResult = (0, checks_1.validateTrigger)(generatedWorkflow, nodeTypes);
9
+ const agentPromptValidationResult = (0, checks_1.validateAgentPrompt)(generatedWorkflow);
10
+ const toolsValidationResult = (0, checks_1.validateTools)(generatedWorkflow, nodeTypes);
11
+ const fromAiValidationResult = (0, checks_1.validateFromAi)(generatedWorkflow, nodeTypes);
12
+ return {
13
+ connections: connectionsValidationResult,
14
+ trigger: triggerValidationResult,
15
+ agentPrompt: agentPromptValidationResult,
16
+ tools: toolsValidationResult,
17
+ fromAi: fromAiValidationResult,
18
+ };
19
+ }
20
+ //# sourceMappingURL=programmatic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"programmatic.js","sourceRoot":"","sources":["../../src/validation/programmatic.ts"],"names":[],"mappings":";;AAYA,wDAmBC;AA7BD,gDAM6B;AAI7B,SAAgB,sBAAsB,CACrC,KAAkC,EAClC,SAAiC;IAEjC,MAAM,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;IAEpC,MAAM,2BAA2B,GAAG,IAAA,4BAAmB,EAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IACtF,MAAM,uBAAuB,GAAG,IAAA,wBAAe,EAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC9E,MAAM,2BAA2B,GAAG,IAAA,4BAAmB,EAAC,iBAAiB,CAAC,CAAC;IAC3E,MAAM,qBAAqB,GAAG,IAAA,sBAAa,EAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC1E,MAAM,sBAAsB,GAAG,IAAA,uBAAc,EAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAE5E,OAAO;QACN,WAAW,EAAE,2BAA2B;QACxC,OAAO,EAAE,uBAAuB;QAChC,WAAW,EAAE,2BAA2B;QACxC,KAAK,EAAE,qBAAqB;QAC5B,MAAM,EAAE,sBAAsB;KAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { INodeTypeDescription, NodeConnectionType } from 'n8n-workflow';
2
+ import type { SimpleWorkflow } from '../types';
3
+ export type ProgrammaticViolationType = 'critical' | 'major' | 'minor';
4
+ export interface ProgrammaticViolation {
5
+ type: ProgrammaticViolationType;
6
+ description: string;
7
+ pointsDeducted: number;
8
+ }
9
+ export interface SingleEvaluatorResult {
10
+ violations: ProgrammaticViolation[];
11
+ score: number;
12
+ }
13
+ export interface ProgrammaticChecksResult {
14
+ connections: ProgrammaticViolation[];
15
+ trigger: ProgrammaticViolation[];
16
+ agentPrompt: ProgrammaticViolation[];
17
+ tools: ProgrammaticViolation[];
18
+ fromAi: ProgrammaticViolation[];
19
+ }
20
+ export interface ProgrammaticEvaluationResult {
21
+ overallScore: number;
22
+ connections: SingleEvaluatorResult;
23
+ trigger: SingleEvaluatorResult;
24
+ agentPrompt: SingleEvaluatorResult;
25
+ tools: SingleEvaluatorResult;
26
+ fromAi: SingleEvaluatorResult;
27
+ }
28
+ export interface ProgrammaticEvaluationInput {
29
+ generatedWorkflow: SimpleWorkflow;
30
+ userPrompt?: string;
31
+ referenceWorkflow?: SimpleWorkflow;
32
+ }
33
+ export interface NodeResolvedConnectionTypesInfo {
34
+ node: SimpleWorkflow['nodes'][0];
35
+ nodeType: INodeTypeDescription;
36
+ resolvedInputs?: Array<{
37
+ type: NodeConnectionType;
38
+ required: boolean;
39
+ }>;
40
+ resolvedOutputs?: Set<NodeConnectionType>;
41
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/validation/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { INodeParameters } from 'n8n-workflow';
2
+ export declare function containsExpression(value: unknown): boolean;
3
+ export declare function nodeParametersContainExpression(parameters: INodeParameters): boolean;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.containsExpression = containsExpression;
4
+ exports.nodeParametersContainExpression = nodeParametersContainExpression;
5
+ const n8n_workflow_1 = require("n8n-workflow");
6
+ function containsExpression(value) {
7
+ if (!(0, n8n_workflow_1.isExpression)(value)) {
8
+ return false;
9
+ }
10
+ return /\{\{.*(\$\(.*?\))|(\$\w+).*}}/.test(value);
11
+ }
12
+ function nodeParametersContainExpression(parameters) {
13
+ for (const value of Object.values(parameters)) {
14
+ if (containsExpression(value)) {
15
+ return true;
16
+ }
17
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
18
+ if (nodeParametersContainExpression(value)) {
19
+ return true;
20
+ }
21
+ }
22
+ if (Array.isArray(value)) {
23
+ for (const item of value) {
24
+ if (containsExpression(item)) {
25
+ return true;
26
+ }
27
+ if (item && typeof item === 'object') {
28
+ if (nodeParametersContainExpression(item)) {
29
+ return true;
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ return false;
36
+ }
37
+ //# sourceMappingURL=expressions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expressions.js","sourceRoot":"","sources":["../../../src/validation/utils/expressions.ts"],"names":[],"mappings":";;AAGA,gDAMC;AAED,0EA4BC;AAtCD,+CAA4C;AAE5C,SAAgB,kBAAkB,CAAC,KAAc;IAChD,IAAI,CAAC,IAAA,2BAAY,EAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACd,CAAC;IAED,OAAO,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,+BAA+B,CAAC,UAA2B;IAC1E,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,IAAI,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjE,IAAI,+BAA+B,CAAC,KAAwB,CAAC,EAAE,CAAC;gBAC/D,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9B,OAAO,IAAI,CAAC;gBACb,CAAC;gBAED,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACtC,IAAI,+BAA+B,CAAC,IAAuB,CAAC,EAAE,CAAC;wBAC9D,OAAO,IAAI,CAAC;oBACb,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { INodeTypeDescription } from 'n8n-workflow';
2
+ export declare function isTool(nodeType: INodeTypeDescription): boolean;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isTool = isTool;
4
+ function isTool(nodeType) {
5
+ return nodeType.codex?.subcategories?.AI?.includes('Tools') ?? false;
6
+ }
7
+ //# sourceMappingURL=is-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-tool.js","sourceRoot":"","sources":["../../../src/validation/utils/is-tool.ts"],"names":[],"mappings":";;AAEA,wBAEC;AAFD,SAAgB,MAAM,CAAC,QAA8B;IACpD,OAAO,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;AACtE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ExpressionString, INodeInputConfiguration, NodeConnectionType } from 'n8n-workflow';
2
+ import type { NodeResolvedConnectionTypesInfo } from '../types';
3
+ export declare function resolveConnections<T = INodeInputConfiguration>(connections: Array<NodeConnectionType | T> | ExpressionString, parameters: Record<string, unknown>, nodeVersion: number): Array<NodeConnectionType | T>;
4
+ export declare function resolveNodeOutputs(nodeInfo: NodeResolvedConnectionTypesInfo): Set<NodeConnectionType>;
5
+ export declare function resolveNodeInputs(nodeInfo: NodeResolvedConnectionTypesInfo): Array<{
6
+ type: NodeConnectionType;
7
+ required: boolean;
8
+ }>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConnections = resolveConnections;
4
+ exports.resolveNodeOutputs = resolveNodeOutputs;
5
+ exports.resolveNodeInputs = resolveNodeInputs;
6
+ const n8n_workflow_1 = require("n8n-workflow");
7
+ function isDynamicConnectionsExpression(connections) {
8
+ return (typeof connections === 'string' && connections.startsWith('={{') && connections.endsWith('}}'));
9
+ }
10
+ function resolveConnections(connections, parameters, nodeVersion) {
11
+ if (Array.isArray(connections)) {
12
+ return connections;
13
+ }
14
+ if (isDynamicConnectionsExpression(connections)) {
15
+ const context = {};
16
+ n8n_workflow_1.Expression.initializeGlobalContext(context);
17
+ Object.assign(context, {
18
+ $parameter: parameters,
19
+ $nodeVersion: nodeVersion,
20
+ });
21
+ const result = n8n_workflow_1.Expression.resolveWithoutWorkflow(connections.substring(1), context);
22
+ if (!Array.isArray(result)) {
23
+ throw new Error('Expression did not resolve to an array');
24
+ }
25
+ return result;
26
+ }
27
+ throw new Error('Unable to resolve connections');
28
+ }
29
+ function resolveNodeOutputs(nodeInfo) {
30
+ const outputTypes = new Set();
31
+ if (!nodeInfo.nodeType.outputs) {
32
+ return outputTypes;
33
+ }
34
+ const resolvedOutputs = resolveConnections(nodeInfo.nodeType.outputs, nodeInfo.node.parameters, nodeInfo.node.typeVersion || 1);
35
+ for (const output of resolvedOutputs) {
36
+ if (typeof output === 'string') {
37
+ outputTypes.add(output);
38
+ }
39
+ else if (typeof output === 'object' && 'type' in output) {
40
+ outputTypes.add(output.type);
41
+ }
42
+ }
43
+ return outputTypes;
44
+ }
45
+ function resolveNodeInputs(nodeInfo) {
46
+ const requiredInputs = [];
47
+ if (!nodeInfo.nodeType.inputs) {
48
+ return requiredInputs;
49
+ }
50
+ const resolvedInputs = resolveConnections(nodeInfo.nodeType.inputs, nodeInfo.node.parameters, nodeInfo.node.typeVersion || 1);
51
+ for (const input of resolvedInputs) {
52
+ if (typeof input === 'string') {
53
+ requiredInputs.push({ type: input, required: input === 'main' });
54
+ }
55
+ else if (typeof input === 'object' && 'type' in input) {
56
+ requiredInputs.push({
57
+ type: input.type,
58
+ required: input.type === 'main' ? true : (input.required ?? false),
59
+ });
60
+ }
61
+ }
62
+ return requiredInputs;
63
+ }
64
+ //# sourceMappingURL=resolve-connections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-connections.js","sourceRoot":"","sources":["../../../src/validation/utils/resolve-connections.ts"],"names":[],"mappings":"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"}