agentic-qe 2.5.6 → 2.5.8

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 (210) hide show
  1. package/.claude/agents/n8n/n8n-base-agent.md +376 -0
  2. package/.claude/agents/n8n/n8n-bdd-scenario-tester.md +613 -0
  3. package/.claude/agents/n8n/n8n-chaos-tester.md +654 -0
  4. package/.claude/agents/n8n/n8n-ci-orchestrator.md +850 -0
  5. package/.claude/agents/n8n/n8n-compliance-validator.md +685 -0
  6. package/.claude/agents/n8n/n8n-expression-validator.md +560 -0
  7. package/.claude/agents/n8n/n8n-integration-test.md +602 -0
  8. package/.claude/agents/n8n/n8n-monitoring-validator.md +589 -0
  9. package/.claude/agents/n8n/n8n-node-validator.md +455 -0
  10. package/.claude/agents/n8n/n8n-performance-tester.md +630 -0
  11. package/.claude/agents/n8n/n8n-security-auditor.md +786 -0
  12. package/.claude/agents/n8n/n8n-trigger-test.md +500 -0
  13. package/.claude/agents/n8n/n8n-unit-tester.md +633 -0
  14. package/.claude/agents/n8n/n8n-version-comparator.md +567 -0
  15. package/.claude/agents/n8n/n8n-workflow-executor.md +392 -0
  16. package/.claude/skills/n8n-expression-testing/SKILL.md +434 -0
  17. package/.claude/skills/n8n-integration-testing-patterns/SKILL.md +540 -0
  18. package/.claude/skills/n8n-security-testing/SKILL.md +599 -0
  19. package/.claude/skills/n8n-trigger-testing-strategies/SKILL.md +541 -0
  20. package/.claude/skills/n8n-workflow-testing-fundamentals/SKILL.md +447 -0
  21. package/CHANGELOG.md +127 -0
  22. package/README.md +7 -4
  23. package/dist/agents/BaseAgent.d.ts +142 -0
  24. package/dist/agents/BaseAgent.d.ts.map +1 -1
  25. package/dist/agents/BaseAgent.js +372 -2
  26. package/dist/agents/BaseAgent.js.map +1 -1
  27. package/dist/agents/TestGeneratorAgent.d.ts +5 -0
  28. package/dist/agents/TestGeneratorAgent.d.ts.map +1 -1
  29. package/dist/agents/TestGeneratorAgent.js +38 -0
  30. package/dist/agents/TestGeneratorAgent.js.map +1 -1
  31. package/dist/agents/index.d.ts +1 -1
  32. package/dist/agents/index.d.ts.map +1 -1
  33. package/dist/agents/index.js.map +1 -1
  34. package/dist/agents/n8n/N8nAPIClient.d.ts +121 -0
  35. package/dist/agents/n8n/N8nAPIClient.d.ts.map +1 -0
  36. package/dist/agents/n8n/N8nAPIClient.js +367 -0
  37. package/dist/agents/n8n/N8nAPIClient.js.map +1 -0
  38. package/dist/agents/n8n/N8nAuditPersistence.d.ts +120 -0
  39. package/dist/agents/n8n/N8nAuditPersistence.d.ts.map +1 -0
  40. package/dist/agents/n8n/N8nAuditPersistence.js +473 -0
  41. package/dist/agents/n8n/N8nAuditPersistence.js.map +1 -0
  42. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.d.ts +159 -0
  43. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.d.ts.map +1 -0
  44. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.js +697 -0
  45. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.js.map +1 -0
  46. package/dist/agents/n8n/N8nBaseAgent.d.ts +126 -0
  47. package/dist/agents/n8n/N8nBaseAgent.d.ts.map +1 -0
  48. package/dist/agents/n8n/N8nBaseAgent.js +446 -0
  49. package/dist/agents/n8n/N8nBaseAgent.js.map +1 -0
  50. package/dist/agents/n8n/N8nCIOrchestratorAgent.d.ts +164 -0
  51. package/dist/agents/n8n/N8nCIOrchestratorAgent.d.ts.map +1 -0
  52. package/dist/agents/n8n/N8nCIOrchestratorAgent.js +610 -0
  53. package/dist/agents/n8n/N8nCIOrchestratorAgent.js.map +1 -0
  54. package/dist/agents/n8n/N8nChaosTesterAgent.d.ts +205 -0
  55. package/dist/agents/n8n/N8nChaosTesterAgent.d.ts.map +1 -0
  56. package/dist/agents/n8n/N8nChaosTesterAgent.js +729 -0
  57. package/dist/agents/n8n/N8nChaosTesterAgent.js.map +1 -0
  58. package/dist/agents/n8n/N8nComplianceValidatorAgent.d.ts +228 -0
  59. package/dist/agents/n8n/N8nComplianceValidatorAgent.d.ts.map +1 -0
  60. package/dist/agents/n8n/N8nComplianceValidatorAgent.js +986 -0
  61. package/dist/agents/n8n/N8nComplianceValidatorAgent.js.map +1 -0
  62. package/dist/agents/n8n/N8nContractTesterAgent.d.ts +213 -0
  63. package/dist/agents/n8n/N8nContractTesterAgent.d.ts.map +1 -0
  64. package/dist/agents/n8n/N8nContractTesterAgent.js +989 -0
  65. package/dist/agents/n8n/N8nContractTesterAgent.js.map +1 -0
  66. package/dist/agents/n8n/N8nExpressionValidatorAgent.d.ts +99 -0
  67. package/dist/agents/n8n/N8nExpressionValidatorAgent.d.ts.map +1 -0
  68. package/dist/agents/n8n/N8nExpressionValidatorAgent.js +632 -0
  69. package/dist/agents/n8n/N8nExpressionValidatorAgent.js.map +1 -0
  70. package/dist/agents/n8n/N8nFailureModeTesterAgent.d.ts +238 -0
  71. package/dist/agents/n8n/N8nFailureModeTesterAgent.d.ts.map +1 -0
  72. package/dist/agents/n8n/N8nFailureModeTesterAgent.js +956 -0
  73. package/dist/agents/n8n/N8nFailureModeTesterAgent.js.map +1 -0
  74. package/dist/agents/n8n/N8nIdempotencyTesterAgent.d.ts +242 -0
  75. package/dist/agents/n8n/N8nIdempotencyTesterAgent.d.ts.map +1 -0
  76. package/dist/agents/n8n/N8nIdempotencyTesterAgent.js +992 -0
  77. package/dist/agents/n8n/N8nIdempotencyTesterAgent.js.map +1 -0
  78. package/dist/agents/n8n/N8nIntegrationTestAgent.d.ts +104 -0
  79. package/dist/agents/n8n/N8nIntegrationTestAgent.d.ts.map +1 -0
  80. package/dist/agents/n8n/N8nIntegrationTestAgent.js +653 -0
  81. package/dist/agents/n8n/N8nIntegrationTestAgent.js.map +1 -0
  82. package/dist/agents/n8n/N8nMonitoringValidatorAgent.d.ts +210 -0
  83. package/dist/agents/n8n/N8nMonitoringValidatorAgent.d.ts.map +1 -0
  84. package/dist/agents/n8n/N8nMonitoringValidatorAgent.js +669 -0
  85. package/dist/agents/n8n/N8nMonitoringValidatorAgent.js.map +1 -0
  86. package/dist/agents/n8n/N8nNodeValidatorAgent.d.ts +142 -0
  87. package/dist/agents/n8n/N8nNodeValidatorAgent.d.ts.map +1 -0
  88. package/dist/agents/n8n/N8nNodeValidatorAgent.js +1090 -0
  89. package/dist/agents/n8n/N8nNodeValidatorAgent.js.map +1 -0
  90. package/dist/agents/n8n/N8nPerformanceTesterAgent.d.ts +198 -0
  91. package/dist/agents/n8n/N8nPerformanceTesterAgent.d.ts.map +1 -0
  92. package/dist/agents/n8n/N8nPerformanceTesterAgent.js +653 -0
  93. package/dist/agents/n8n/N8nPerformanceTesterAgent.js.map +1 -0
  94. package/dist/agents/n8n/N8nReplayabilityTesterAgent.d.ts +245 -0
  95. package/dist/agents/n8n/N8nReplayabilityTesterAgent.d.ts.map +1 -0
  96. package/dist/agents/n8n/N8nReplayabilityTesterAgent.js +952 -0
  97. package/dist/agents/n8n/N8nReplayabilityTesterAgent.js.map +1 -0
  98. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.d.ts +325 -0
  99. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.d.ts.map +1 -0
  100. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.js +1187 -0
  101. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.js.map +1 -0
  102. package/dist/agents/n8n/N8nSecurityAuditorAgent.d.ts +91 -0
  103. package/dist/agents/n8n/N8nSecurityAuditorAgent.d.ts.map +1 -0
  104. package/dist/agents/n8n/N8nSecurityAuditorAgent.js +825 -0
  105. package/dist/agents/n8n/N8nSecurityAuditorAgent.js.map +1 -0
  106. package/dist/agents/n8n/N8nTestHarness.d.ts +131 -0
  107. package/dist/agents/n8n/N8nTestHarness.d.ts.map +1 -0
  108. package/dist/agents/n8n/N8nTestHarness.js +456 -0
  109. package/dist/agents/n8n/N8nTestHarness.js.map +1 -0
  110. package/dist/agents/n8n/N8nTriggerTestAgent.d.ts +119 -0
  111. package/dist/agents/n8n/N8nTriggerTestAgent.d.ts.map +1 -0
  112. package/dist/agents/n8n/N8nTriggerTestAgent.js +652 -0
  113. package/dist/agents/n8n/N8nTriggerTestAgent.js.map +1 -0
  114. package/dist/agents/n8n/N8nUnitTesterAgent.d.ts +130 -0
  115. package/dist/agents/n8n/N8nUnitTesterAgent.d.ts.map +1 -0
  116. package/dist/agents/n8n/N8nUnitTesterAgent.js +522 -0
  117. package/dist/agents/n8n/N8nUnitTesterAgent.js.map +1 -0
  118. package/dist/agents/n8n/N8nVersionComparatorAgent.d.ts +201 -0
  119. package/dist/agents/n8n/N8nVersionComparatorAgent.d.ts.map +1 -0
  120. package/dist/agents/n8n/N8nVersionComparatorAgent.js +645 -0
  121. package/dist/agents/n8n/N8nVersionComparatorAgent.js.map +1 -0
  122. package/dist/agents/n8n/N8nWorkflowExecutorAgent.d.ts +120 -0
  123. package/dist/agents/n8n/N8nWorkflowExecutorAgent.d.ts.map +1 -0
  124. package/dist/agents/n8n/N8nWorkflowExecutorAgent.js +347 -0
  125. package/dist/agents/n8n/N8nWorkflowExecutorAgent.js.map +1 -0
  126. package/dist/agents/n8n/index.d.ts +119 -0
  127. package/dist/agents/n8n/index.d.ts.map +1 -0
  128. package/dist/agents/n8n/index.js +298 -0
  129. package/dist/agents/n8n/index.js.map +1 -0
  130. package/dist/agents/n8n/types.d.ts +486 -0
  131. package/dist/agents/n8n/types.d.ts.map +1 -0
  132. package/dist/agents/n8n/types.js +8 -0
  133. package/dist/agents/n8n/types.js.map +1 -0
  134. package/dist/cli/init/agents.d.ts.map +1 -1
  135. package/dist/cli/init/agents.js +29 -0
  136. package/dist/cli/init/agents.js.map +1 -1
  137. package/dist/cli/init/skills.d.ts.map +1 -1
  138. package/dist/cli/init/skills.js +7 -1
  139. package/dist/cli/init/skills.js.map +1 -1
  140. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  141. package/dist/core/memory/RuVectorPatternStore.d.ts +90 -0
  142. package/dist/core/memory/RuVectorPatternStore.d.ts.map +1 -1
  143. package/dist/core/memory/RuVectorPatternStore.js +209 -0
  144. package/dist/core/memory/RuVectorPatternStore.js.map +1 -1
  145. package/dist/learning/FederatedManager.d.ts +232 -0
  146. package/dist/learning/FederatedManager.d.ts.map +1 -0
  147. package/dist/learning/FederatedManager.js +489 -0
  148. package/dist/learning/FederatedManager.js.map +1 -0
  149. package/dist/learning/HNSWPatternAdapter.d.ts +117 -0
  150. package/dist/learning/HNSWPatternAdapter.d.ts.map +1 -0
  151. package/dist/learning/HNSWPatternAdapter.js +262 -0
  152. package/dist/learning/HNSWPatternAdapter.js.map +1 -0
  153. package/dist/learning/LearningEngine.d.ts +27 -0
  154. package/dist/learning/LearningEngine.d.ts.map +1 -1
  155. package/dist/learning/LearningEngine.js +75 -1
  156. package/dist/learning/LearningEngine.js.map +1 -1
  157. package/dist/learning/PatternCurator.d.ts +217 -0
  158. package/dist/learning/PatternCurator.d.ts.map +1 -0
  159. package/dist/learning/PatternCurator.js +393 -0
  160. package/dist/learning/PatternCurator.js.map +1 -0
  161. package/dist/learning/index.d.ts +6 -0
  162. package/dist/learning/index.d.ts.map +1 -1
  163. package/dist/learning/index.js +16 -1
  164. package/dist/learning/index.js.map +1 -1
  165. package/dist/learning/types.d.ts +4 -0
  166. package/dist/learning/types.d.ts.map +1 -1
  167. package/dist/mcp/server-instructions.d.ts +1 -1
  168. package/dist/mcp/server-instructions.js +1 -1
  169. package/dist/memory/HNSWPatternStore.d.ts +176 -0
  170. package/dist/memory/HNSWPatternStore.d.ts.map +1 -0
  171. package/dist/memory/HNSWPatternStore.js +392 -0
  172. package/dist/memory/HNSWPatternStore.js.map +1 -0
  173. package/dist/memory/index.d.ts +8 -0
  174. package/dist/memory/index.d.ts.map +1 -0
  175. package/dist/memory/index.js +13 -0
  176. package/dist/memory/index.js.map +1 -0
  177. package/dist/providers/HybridRouter.d.ts +85 -4
  178. package/dist/providers/HybridRouter.d.ts.map +1 -1
  179. package/dist/providers/HybridRouter.js +332 -10
  180. package/dist/providers/HybridRouter.js.map +1 -1
  181. package/dist/providers/LLMBaselineTracker.d.ts +120 -0
  182. package/dist/providers/LLMBaselineTracker.d.ts.map +1 -0
  183. package/dist/providers/LLMBaselineTracker.js +305 -0
  184. package/dist/providers/LLMBaselineTracker.js.map +1 -0
  185. package/dist/providers/OpenRouterProvider.d.ts +26 -0
  186. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  187. package/dist/providers/OpenRouterProvider.js +75 -6
  188. package/dist/providers/OpenRouterProvider.js.map +1 -1
  189. package/dist/providers/RuVectorClient.d.ts +259 -0
  190. package/dist/providers/RuVectorClient.d.ts.map +1 -0
  191. package/dist/providers/RuVectorClient.js +416 -0
  192. package/dist/providers/RuVectorClient.js.map +1 -0
  193. package/dist/providers/RuvllmPatternCurator.d.ts +116 -0
  194. package/dist/providers/RuvllmPatternCurator.d.ts.map +1 -0
  195. package/dist/providers/RuvllmPatternCurator.js +323 -0
  196. package/dist/providers/RuvllmPatternCurator.js.map +1 -0
  197. package/dist/providers/RuvllmProvider.d.ts +233 -1
  198. package/dist/providers/RuvllmProvider.d.ts.map +1 -1
  199. package/dist/providers/RuvllmProvider.js +781 -11
  200. package/dist/providers/RuvllmProvider.js.map +1 -1
  201. package/dist/providers/index.d.ts +5 -1
  202. package/dist/providers/index.d.ts.map +1 -1
  203. package/dist/providers/index.js +12 -2
  204. package/dist/providers/index.js.map +1 -1
  205. package/dist/utils/ruvllm-loader.d.ts +98 -1
  206. package/dist/utils/ruvllm-loader.d.ts.map +1 -1
  207. package/dist/utils/ruvllm-loader.js.map +1 -1
  208. package/docs/reference/agents.md +91 -2
  209. package/docs/reference/skills.md +97 -2
  210. package/package.json +2 -2
@@ -0,0 +1,1090 @@
1
+ "use strict";
2
+ /**
3
+ * N8nNodeValidatorAgent
4
+ *
5
+ * Validates n8n node configurations, connections, and data mappings:
6
+ * - Node structure validation
7
+ * - Connection integrity checks
8
+ * - Credential reference validation
9
+ * - Data mapping validation
10
+ * - Conditional routing logic validation
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.N8nNodeValidatorAgent = void 0;
14
+ const N8nBaseAgent_1 = require("./N8nBaseAgent");
15
+ // Node type configurations for validation
16
+ // Extended coverage: 70+ node types (from ~12)
17
+ const NODE_CONFIGS = {
18
+ // ============================================================================
19
+ // Trigger Nodes
20
+ // ============================================================================
21
+ 'n8n-nodes-base.webhook': {
22
+ requiredParams: ['httpMethod', 'path'],
23
+ optionalParams: ['authentication', 'responseMode', 'responseData'],
24
+ requiresCredential: false,
25
+ category: 'trigger',
26
+ },
27
+ 'n8n-nodes-base.manualTrigger': {
28
+ requiredParams: [],
29
+ optionalParams: [],
30
+ requiresCredential: false,
31
+ category: 'trigger',
32
+ },
33
+ 'n8n-nodes-base.scheduleTrigger': {
34
+ requiredParams: ['rule'],
35
+ optionalParams: ['cronExpression'],
36
+ requiresCredential: false,
37
+ category: 'trigger',
38
+ },
39
+ 'n8n-nodes-base.emailReadImap': {
40
+ requiredParams: [],
41
+ optionalParams: ['mailbox', 'format'],
42
+ requiresCredential: true,
43
+ credentialTypes: ['imap'],
44
+ category: 'trigger',
45
+ },
46
+ 'n8n-nodes-base.rssFeedReadTrigger': {
47
+ requiredParams: ['feedUrl'],
48
+ optionalParams: ['pollTimes'],
49
+ requiresCredential: false,
50
+ category: 'trigger',
51
+ },
52
+ // ============================================================================
53
+ // Core/Logic Nodes
54
+ // ============================================================================
55
+ 'n8n-nodes-base.if': {
56
+ requiredParams: ['conditions'],
57
+ optionalParams: [],
58
+ requiresCredential: false,
59
+ category: 'logic',
60
+ },
61
+ 'n8n-nodes-base.switch': {
62
+ requiredParams: ['rules'],
63
+ optionalParams: ['fallbackOutput'],
64
+ requiresCredential: false,
65
+ category: 'logic',
66
+ },
67
+ 'n8n-nodes-base.merge': {
68
+ requiredParams: ['mode'],
69
+ optionalParams: ['joinMode', 'propertyName1', 'propertyName2'],
70
+ requiresCredential: false,
71
+ category: 'logic',
72
+ },
73
+ 'n8n-nodes-base.splitInBatches': {
74
+ requiredParams: ['batchSize'],
75
+ optionalParams: [],
76
+ requiresCredential: false,
77
+ category: 'logic',
78
+ },
79
+ 'n8n-nodes-base.wait': {
80
+ requiredParams: [],
81
+ optionalParams: ['resume', 'amount', 'unit'],
82
+ requiresCredential: false,
83
+ category: 'logic',
84
+ },
85
+ 'n8n-nodes-base.noOp': {
86
+ requiredParams: [],
87
+ optionalParams: [],
88
+ requiresCredential: false,
89
+ category: 'logic',
90
+ },
91
+ 'n8n-nodes-base.filter': {
92
+ requiredParams: ['conditions'],
93
+ optionalParams: [],
94
+ requiresCredential: false,
95
+ category: 'logic',
96
+ },
97
+ 'n8n-nodes-base.limit': {
98
+ requiredParams: ['maxItems'],
99
+ optionalParams: [],
100
+ requiresCredential: false,
101
+ category: 'logic',
102
+ },
103
+ 'n8n-nodes-base.removeDuplicates': {
104
+ requiredParams: [],
105
+ optionalParams: ['compareMode', 'fieldsToCompare'],
106
+ requiresCredential: false,
107
+ category: 'logic',
108
+ },
109
+ 'n8n-nodes-base.sort': {
110
+ requiredParams: ['sortFieldsUi'],
111
+ optionalParams: [],
112
+ requiresCredential: false,
113
+ category: 'logic',
114
+ },
115
+ // ============================================================================
116
+ // Data Transformation Nodes
117
+ // ============================================================================
118
+ 'n8n-nodes-base.set': {
119
+ requiredParams: [],
120
+ optionalParams: ['mode', 'assignments', 'keepOnlySet'],
121
+ requiresCredential: false,
122
+ category: 'transform',
123
+ },
124
+ 'n8n-nodes-base.code': {
125
+ requiredParams: [],
126
+ optionalParams: ['jsCode', 'mode', 'language'],
127
+ requiresCredential: false,
128
+ category: 'transform',
129
+ },
130
+ 'n8n-nodes-base.itemLists': {
131
+ requiredParams: ['operation'],
132
+ optionalParams: ['fieldToSplitOut', 'include'],
133
+ requiresCredential: false,
134
+ category: 'transform',
135
+ },
136
+ 'n8n-nodes-base.dateTime': {
137
+ requiredParams: ['action'],
138
+ optionalParams: ['format', 'timezone'],
139
+ requiresCredential: false,
140
+ category: 'transform',
141
+ },
142
+ 'n8n-nodes-base.crypto': {
143
+ requiredParams: ['action'],
144
+ optionalParams: ['type', 'encoding'],
145
+ requiresCredential: false,
146
+ category: 'transform',
147
+ },
148
+ 'n8n-nodes-base.html': {
149
+ requiredParams: ['operation'],
150
+ optionalParams: ['cssSelector', 'options'],
151
+ requiresCredential: false,
152
+ category: 'transform',
153
+ },
154
+ 'n8n-nodes-base.xml': {
155
+ requiredParams: ['mode'],
156
+ optionalParams: ['options'],
157
+ requiresCredential: false,
158
+ category: 'transform',
159
+ },
160
+ 'n8n-nodes-base.spreadsheetFile': {
161
+ requiredParams: ['operation'],
162
+ optionalParams: ['fileFormat', 'options'],
163
+ requiresCredential: false,
164
+ category: 'transform',
165
+ },
166
+ 'n8n-nodes-base.markdown': {
167
+ requiredParams: ['mode'],
168
+ optionalParams: ['options'],
169
+ requiresCredential: false,
170
+ category: 'transform',
171
+ },
172
+ 'n8n-nodes-base.compressFiles': {
173
+ requiredParams: ['operation'],
174
+ optionalParams: ['outputFormat'],
175
+ requiresCredential: false,
176
+ category: 'transform',
177
+ },
178
+ // ============================================================================
179
+ // HTTP/API Nodes
180
+ // ============================================================================
181
+ 'n8n-nodes-base.httpRequest': {
182
+ requiredParams: ['url', 'method'],
183
+ optionalParams: ['authentication', 'bodyParameters', 'headers', 'queryParameters'],
184
+ requiresCredential: false,
185
+ category: 'http',
186
+ },
187
+ 'n8n-nodes-base.respondToWebhook': {
188
+ requiredParams: [],
189
+ optionalParams: ['respondWith', 'responseBody', 'responseHeaders'],
190
+ requiresCredential: false,
191
+ category: 'http',
192
+ },
193
+ 'n8n-nodes-base.graphql': {
194
+ requiredParams: ['endpoint', 'query'],
195
+ optionalParams: ['authentication', 'variables'],
196
+ requiresCredential: false,
197
+ category: 'http',
198
+ },
199
+ 'n8n-nodes-base.soapRequest': {
200
+ requiredParams: ['url', 'bodyXml'],
201
+ optionalParams: ['authentication'],
202
+ requiresCredential: false,
203
+ category: 'http',
204
+ },
205
+ // ============================================================================
206
+ // Database Nodes
207
+ // ============================================================================
208
+ 'n8n-nodes-base.postgres': {
209
+ requiredParams: ['operation'],
210
+ optionalParams: ['query', 'table', 'schema'],
211
+ requiresCredential: true,
212
+ credentialTypes: ['postgres'],
213
+ category: 'database',
214
+ },
215
+ 'n8n-nodes-base.mysql': {
216
+ requiredParams: ['operation'],
217
+ optionalParams: ['query', 'table'],
218
+ requiresCredential: true,
219
+ credentialTypes: ['mysql'],
220
+ category: 'database',
221
+ },
222
+ 'n8n-nodes-base.mongodb': {
223
+ requiredParams: ['operation'],
224
+ optionalParams: ['collection', 'query'],
225
+ requiresCredential: true,
226
+ credentialTypes: ['mongoDb'],
227
+ category: 'database',
228
+ },
229
+ 'n8n-nodes-base.redis': {
230
+ requiredParams: ['operation'],
231
+ optionalParams: ['key', 'keyType'],
232
+ requiresCredential: true,
233
+ credentialTypes: ['redis'],
234
+ category: 'database',
235
+ },
236
+ 'n8n-nodes-base.mssql': {
237
+ requiredParams: ['operation'],
238
+ optionalParams: ['query', 'table'],
239
+ requiresCredential: true,
240
+ credentialTypes: ['microsoftSql'],
241
+ category: 'database',
242
+ },
243
+ 'n8n-nodes-base.elasticsearch': {
244
+ requiredParams: ['operation'],
245
+ optionalParams: ['index', 'documentId'],
246
+ requiresCredential: true,
247
+ credentialTypes: ['elasticsearch'],
248
+ category: 'database',
249
+ },
250
+ 'n8n-nodes-base.supabase': {
251
+ requiredParams: ['operation'],
252
+ optionalParams: ['tableId'],
253
+ requiresCredential: true,
254
+ credentialTypes: ['supabaseApi'],
255
+ category: 'database',
256
+ },
257
+ 'n8n-nodes-base.snowflake': {
258
+ requiredParams: ['operation'],
259
+ optionalParams: ['query'],
260
+ requiresCredential: true,
261
+ credentialTypes: ['snowflake'],
262
+ category: 'database',
263
+ },
264
+ 'n8n-nodes-base.qdrant': {
265
+ requiredParams: ['operation'],
266
+ optionalParams: ['collection'],
267
+ requiresCredential: true,
268
+ credentialTypes: ['qdrantApi'],
269
+ category: 'database',
270
+ },
271
+ 'n8n-nodes-base.pinecone': {
272
+ requiredParams: ['operation'],
273
+ optionalParams: ['index'],
274
+ requiresCredential: true,
275
+ credentialTypes: ['pineconeApi'],
276
+ category: 'database',
277
+ },
278
+ // ============================================================================
279
+ // Communication Nodes
280
+ // ============================================================================
281
+ 'n8n-nodes-base.slack': {
282
+ requiredParams: ['resource', 'operation'],
283
+ optionalParams: ['channel', 'text', 'attachments'],
284
+ requiresCredential: true,
285
+ credentialTypes: ['slackApi', 'slackOAuth2Api'],
286
+ category: 'communication',
287
+ },
288
+ 'n8n-nodes-base.discord': {
289
+ requiredParams: ['resource', 'operation'],
290
+ optionalParams: ['channelId', 'content'],
291
+ requiresCredential: true,
292
+ credentialTypes: ['discordApi', 'discordWebhookApi'],
293
+ category: 'communication',
294
+ },
295
+ 'n8n-nodes-base.telegram': {
296
+ requiredParams: ['resource', 'operation'],
297
+ optionalParams: ['chatId', 'text'],
298
+ requiresCredential: true,
299
+ credentialTypes: ['telegramApi'],
300
+ category: 'communication',
301
+ },
302
+ 'n8n-nodes-base.microsoftTeams': {
303
+ requiredParams: ['resource', 'operation'],
304
+ optionalParams: ['teamId', 'channelId', 'message'],
305
+ requiresCredential: true,
306
+ credentialTypes: ['microsoftTeamsOAuth2Api'],
307
+ category: 'communication',
308
+ },
309
+ 'n8n-nodes-base.emailSend': {
310
+ requiredParams: ['toEmail', 'subject'],
311
+ optionalParams: ['text', 'html', 'attachments'],
312
+ requiresCredential: true,
313
+ credentialTypes: ['smtp'],
314
+ category: 'communication',
315
+ },
316
+ 'n8n-nodes-base.gmail': {
317
+ requiredParams: ['resource', 'operation'],
318
+ optionalParams: ['subject', 'message'],
319
+ requiresCredential: true,
320
+ credentialTypes: ['gmailOAuth2'],
321
+ category: 'communication',
322
+ },
323
+ 'n8n-nodes-base.sendGrid': {
324
+ requiredParams: ['resource', 'operation'],
325
+ optionalParams: ['toEmail', 'subject'],
326
+ requiresCredential: true,
327
+ credentialTypes: ['sendGridApi'],
328
+ category: 'communication',
329
+ },
330
+ 'n8n-nodes-base.twilio': {
331
+ requiredParams: ['resource', 'operation'],
332
+ optionalParams: ['from', 'to', 'message'],
333
+ requiresCredential: true,
334
+ credentialTypes: ['twilioApi'],
335
+ category: 'communication',
336
+ },
337
+ // ============================================================================
338
+ // Productivity/SaaS Nodes
339
+ // ============================================================================
340
+ 'n8n-nodes-base.googleSheets': {
341
+ requiredParams: ['operation'],
342
+ optionalParams: ['documentId', 'sheetName', 'range'],
343
+ requiresCredential: true,
344
+ credentialTypes: ['googleSheetsOAuth2Api'],
345
+ category: 'productivity',
346
+ },
347
+ 'n8n-nodes-base.googleDrive': {
348
+ requiredParams: ['operation'],
349
+ optionalParams: ['fileId', 'folderId'],
350
+ requiresCredential: true,
351
+ credentialTypes: ['googleDriveOAuth2Api'],
352
+ category: 'productivity',
353
+ },
354
+ 'n8n-nodes-base.googleDocs': {
355
+ requiredParams: ['operation'],
356
+ optionalParams: ['documentId'],
357
+ requiresCredential: true,
358
+ credentialTypes: ['googleDocsOAuth2Api'],
359
+ category: 'productivity',
360
+ },
361
+ 'n8n-nodes-base.googleCalendar': {
362
+ requiredParams: ['resource', 'operation'],
363
+ optionalParams: ['calendar', 'eventId'],
364
+ requiresCredential: true,
365
+ credentialTypes: ['googleCalendarOAuth2Api'],
366
+ category: 'productivity',
367
+ },
368
+ 'n8n-nodes-base.notion': {
369
+ requiredParams: ['resource', 'operation'],
370
+ optionalParams: ['databaseId', 'pageId'],
371
+ requiresCredential: true,
372
+ credentialTypes: ['notionApi'],
373
+ category: 'productivity',
374
+ },
375
+ 'n8n-nodes-base.airtable': {
376
+ requiredParams: ['operation'],
377
+ optionalParams: ['baseId', 'tableId'],
378
+ requiresCredential: true,
379
+ credentialTypes: ['airtableApi', 'airtableTokenApi'],
380
+ category: 'productivity',
381
+ },
382
+ 'n8n-nodes-base.trello': {
383
+ requiredParams: ['resource', 'operation'],
384
+ optionalParams: ['boardId', 'listId', 'cardId'],
385
+ requiresCredential: true,
386
+ credentialTypes: ['trelloApi'],
387
+ category: 'productivity',
388
+ },
389
+ 'n8n-nodes-base.asana': {
390
+ requiredParams: ['resource', 'operation'],
391
+ optionalParams: ['workspaceId', 'projectId'],
392
+ requiresCredential: true,
393
+ credentialTypes: ['asanaApi'],
394
+ category: 'productivity',
395
+ },
396
+ 'n8n-nodes-base.jira': {
397
+ requiredParams: ['resource', 'operation'],
398
+ optionalParams: ['issueKey', 'projectId'],
399
+ requiresCredential: true,
400
+ credentialTypes: ['jiraSoftwareCloudApi', 'jiraSoftwareServerApi'],
401
+ category: 'productivity',
402
+ },
403
+ 'n8n-nodes-base.linearApp': {
404
+ requiredParams: ['resource', 'operation'],
405
+ optionalParams: ['issueId', 'teamId'],
406
+ requiresCredential: true,
407
+ credentialTypes: ['linearApi'],
408
+ category: 'productivity',
409
+ },
410
+ 'n8n-nodes-base.dropbox': {
411
+ requiredParams: ['resource', 'operation'],
412
+ optionalParams: ['path'],
413
+ requiresCredential: true,
414
+ credentialTypes: ['dropboxApi', 'dropboxOAuth2Api'],
415
+ category: 'productivity',
416
+ },
417
+ 'n8n-nodes-base.box': {
418
+ requiredParams: ['resource', 'operation'],
419
+ optionalParams: ['fileId', 'folderId'],
420
+ requiresCredential: true,
421
+ credentialTypes: ['boxOAuth2Api'],
422
+ category: 'productivity',
423
+ },
424
+ // ============================================================================
425
+ // Developer/DevOps Nodes
426
+ // ============================================================================
427
+ 'n8n-nodes-base.github': {
428
+ requiredParams: ['resource', 'operation'],
429
+ optionalParams: ['owner', 'repository'],
430
+ requiresCredential: true,
431
+ credentialTypes: ['githubApi', 'githubOAuth2Api'],
432
+ category: 'devops',
433
+ },
434
+ 'n8n-nodes-base.gitlab': {
435
+ requiredParams: ['resource', 'operation'],
436
+ optionalParams: ['owner', 'repository'],
437
+ requiresCredential: true,
438
+ credentialTypes: ['gitlabApi', 'gitlabOAuth2Api'],
439
+ category: 'devops',
440
+ },
441
+ 'n8n-nodes-base.bitbucket': {
442
+ requiredParams: ['resource', 'operation'],
443
+ optionalParams: ['workspace', 'repositorySlug'],
444
+ requiresCredential: true,
445
+ credentialTypes: ['bitbucketApi'],
446
+ category: 'devops',
447
+ },
448
+ 'n8n-nodes-base.executeCommand': {
449
+ requiredParams: ['command'],
450
+ optionalParams: ['cwd'],
451
+ requiresCredential: false,
452
+ category: 'devops',
453
+ },
454
+ 'n8n-nodes-base.ssh': {
455
+ requiredParams: ['command'],
456
+ optionalParams: ['cwd'],
457
+ requiresCredential: true,
458
+ credentialTypes: ['sshPassword', 'sshPrivateKey'],
459
+ category: 'devops',
460
+ },
461
+ 'n8n-nodes-base.ftp': {
462
+ requiredParams: ['operation'],
463
+ optionalParams: ['path'],
464
+ requiresCredential: true,
465
+ credentialTypes: ['ftp', 'sftp'],
466
+ category: 'devops',
467
+ },
468
+ 'n8n-nodes-base.awsS3': {
469
+ requiredParams: ['operation'],
470
+ optionalParams: ['bucketName', 'fileKey'],
471
+ requiresCredential: true,
472
+ credentialTypes: ['aws'],
473
+ category: 'devops',
474
+ },
475
+ 'n8n-nodes-base.awsLambda': {
476
+ requiredParams: ['operation'],
477
+ optionalParams: ['functionName'],
478
+ requiresCredential: true,
479
+ credentialTypes: ['aws'],
480
+ category: 'devops',
481
+ },
482
+ 'n8n-nodes-base.awsSns': {
483
+ requiredParams: ['operation'],
484
+ optionalParams: ['topicArn'],
485
+ requiresCredential: true,
486
+ credentialTypes: ['aws'],
487
+ category: 'devops',
488
+ },
489
+ 'n8n-nodes-base.awsSqs': {
490
+ requiredParams: ['operation'],
491
+ optionalParams: ['queueUrl'],
492
+ requiresCredential: true,
493
+ credentialTypes: ['aws'],
494
+ category: 'devops',
495
+ },
496
+ // ============================================================================
497
+ // CRM/Marketing Nodes
498
+ // ============================================================================
499
+ 'n8n-nodes-base.salesforce': {
500
+ requiredParams: ['resource', 'operation'],
501
+ optionalParams: ['accountId', 'contactId'],
502
+ requiresCredential: true,
503
+ credentialTypes: ['salesforceOAuth2Api'],
504
+ category: 'crm',
505
+ },
506
+ 'n8n-nodes-base.hubspot': {
507
+ requiredParams: ['resource', 'operation'],
508
+ optionalParams: ['contactId'],
509
+ requiresCredential: true,
510
+ credentialTypes: ['hubspotApi', 'hubspotOAuth2Api'],
511
+ category: 'crm',
512
+ },
513
+ 'n8n-nodes-base.mailchimp': {
514
+ requiredParams: ['resource', 'operation'],
515
+ optionalParams: ['listId'],
516
+ requiresCredential: true,
517
+ credentialTypes: ['mailchimpApi'],
518
+ category: 'crm',
519
+ },
520
+ 'n8n-nodes-base.stripe': {
521
+ requiredParams: ['resource', 'operation'],
522
+ optionalParams: ['customerId'],
523
+ requiresCredential: true,
524
+ credentialTypes: ['stripeApi'],
525
+ category: 'crm',
526
+ },
527
+ 'n8n-nodes-base.shopify': {
528
+ requiredParams: ['resource', 'operation'],
529
+ optionalParams: ['orderId', 'productId'],
530
+ requiresCredential: true,
531
+ credentialTypes: ['shopifyApi', 'shopifyAccessTokenApi'],
532
+ category: 'crm',
533
+ },
534
+ // ============================================================================
535
+ // AI/LLM Nodes
536
+ // ============================================================================
537
+ '@n8n/n8n-nodes-langchain.openAi': {
538
+ requiredParams: ['resource', 'operation'],
539
+ optionalParams: ['model', 'prompt', 'messages'],
540
+ requiresCredential: true,
541
+ credentialTypes: ['openAiApi'],
542
+ category: 'ai',
543
+ },
544
+ '@n8n/n8n-nodes-langchain.agent': {
545
+ requiredParams: [],
546
+ optionalParams: ['promptType', 'text'],
547
+ requiresCredential: false,
548
+ category: 'ai',
549
+ },
550
+ '@n8n/n8n-nodes-langchain.lmChatOpenAi': {
551
+ requiredParams: [],
552
+ optionalParams: ['model', 'options'],
553
+ requiresCredential: true,
554
+ credentialTypes: ['openAiApi'],
555
+ category: 'ai',
556
+ },
557
+ '@n8n/n8n-nodes-langchain.lmChatAnthropic': {
558
+ requiredParams: [],
559
+ optionalParams: ['model', 'options'],
560
+ requiresCredential: true,
561
+ credentialTypes: ['anthropicApi'],
562
+ category: 'ai',
563
+ },
564
+ '@n8n/n8n-nodes-langchain.vectorStoreInMemory': {
565
+ requiredParams: [],
566
+ optionalParams: ['mode'],
567
+ requiresCredential: false,
568
+ category: 'ai',
569
+ },
570
+ '@n8n/n8n-nodes-langchain.embeddingsOpenAi': {
571
+ requiredParams: [],
572
+ optionalParams: ['model', 'options'],
573
+ requiresCredential: true,
574
+ credentialTypes: ['openAiApi'],
575
+ category: 'ai',
576
+ },
577
+ '@n8n/n8n-nodes-langchain.toolHttpRequest': {
578
+ requiredParams: ['url'],
579
+ optionalParams: ['method', 'description'],
580
+ requiresCredential: false,
581
+ category: 'ai',
582
+ },
583
+ '@n8n/n8n-nodes-langchain.toolCode': {
584
+ requiredParams: ['jsCode'],
585
+ optionalParams: ['name', 'description'],
586
+ requiresCredential: false,
587
+ category: 'ai',
588
+ },
589
+ '@n8n/n8n-nodes-langchain.memoryBufferWindow': {
590
+ requiredParams: [],
591
+ optionalParams: ['sessionIdType', 'contextWindowLength'],
592
+ requiresCredential: false,
593
+ category: 'ai',
594
+ },
595
+ '@n8n/n8n-nodes-langchain.chainSummarization': {
596
+ requiredParams: [],
597
+ optionalParams: ['options'],
598
+ requiresCredential: false,
599
+ category: 'ai',
600
+ },
601
+ };
602
+ class N8nNodeValidatorAgent extends N8nBaseAgent_1.N8nBaseAgent {
603
+ constructor(config) {
604
+ const capabilities = [
605
+ {
606
+ name: 'node-validation',
607
+ version: '1.0.0',
608
+ description: 'Validate n8n node configurations',
609
+ parameters: {},
610
+ },
611
+ {
612
+ name: 'connection-validation',
613
+ version: '1.0.0',
614
+ description: 'Validate connections between nodes',
615
+ parameters: {},
616
+ },
617
+ {
618
+ name: 'credential-validation',
619
+ version: '1.0.0',
620
+ description: 'Validate credential references',
621
+ parameters: {},
622
+ },
623
+ {
624
+ name: 'data-mapping-validation',
625
+ version: '1.0.0',
626
+ description: 'Validate data mappings between nodes',
627
+ parameters: {},
628
+ },
629
+ ];
630
+ super({
631
+ ...config,
632
+ type: 'n8n-node-validator',
633
+ capabilities: [...capabilities, ...(config.capabilities || [])],
634
+ });
635
+ }
636
+ async performTask(task) {
637
+ const validationTask = task;
638
+ if (validationTask.type !== 'node-validation') {
639
+ throw new Error(`Unsupported task type: ${validationTask.type}`);
640
+ }
641
+ return this.validateWorkflow(validationTask.target, validationTask.options);
642
+ }
643
+ /**
644
+ * Validate entire workflow with optional REAL execution test
645
+ */
646
+ async validateWorkflow(workflowId, options) {
647
+ const workflow = await this.getWorkflow(workflowId);
648
+ // Validate nodes (static analysis)
649
+ const nodeResults = await this.validateNodes(workflow, options?.strictMode);
650
+ // Validate connections (static analysis)
651
+ const connectionResults = this.validateConnections(workflow);
652
+ // Validate credentials (static analysis)
653
+ let credentialResults = [];
654
+ if (options?.validateCredentials) {
655
+ credentialResults = await this.validateCredentials(workflow);
656
+ }
657
+ // RUNTIME VALIDATION: Actually execute the workflow to verify nodes work
658
+ let runtimeValidation;
659
+ if (options?.executeRuntimeTest) {
660
+ runtimeValidation = await this.executeRuntimeValidation(workflowId, options.testInput || {});
661
+ // Add runtime errors to node results
662
+ for (const error of runtimeValidation.errors) {
663
+ const nodeResult = nodeResults.find(n => n.nodeName === error.nodeName);
664
+ if (nodeResult) {
665
+ nodeResult.valid = false;
666
+ nodeResult.issues.push({
667
+ severity: 'error',
668
+ code: 'RUNTIME_ERROR',
669
+ message: `Runtime execution failed: ${error.errorMessage}`,
670
+ node: error.nodeName,
671
+ });
672
+ }
673
+ }
674
+ }
675
+ // Calculate summary
676
+ const validNodes = nodeResults.filter(r => r.valid).length;
677
+ const validConnections = connectionResults.filter(r => r.valid).length;
678
+ const totalIssues = [
679
+ ...nodeResults.flatMap(r => r.issues),
680
+ ...connectionResults.flatMap(r => r.issues),
681
+ ];
682
+ const issues = totalIssues.filter(i => i.severity === 'error').length;
683
+ const warnings = totalIssues.filter(i => i.severity === 'warning').length;
684
+ // Calculate score (including runtime validation if performed)
685
+ let nodeScore = workflow.nodes.length > 0 ? (validNodes / workflow.nodes.length) * 40 : 40;
686
+ const connectionScore = Object.keys(workflow.connections).length > 0
687
+ ? (validConnections / Object.keys(workflow.connections).length) * 20
688
+ : 20;
689
+ const credentialScore = credentialResults.length > 0
690
+ ? (credentialResults.filter(r => r.valid).length / credentialResults.length) * 15
691
+ : 15;
692
+ // Runtime score is worth 25% if executed
693
+ let runtimeScore = 25; // Default if not executed
694
+ if (runtimeValidation?.executed) {
695
+ const runtimePassed = runtimeValidation.status === 'success' &&
696
+ runtimeValidation.nodesFailed.length === 0;
697
+ runtimeScore = runtimePassed ? 25 : 0;
698
+ }
699
+ const score = Math.round(nodeScore + connectionScore + credentialScore + runtimeScore);
700
+ const result = {
701
+ workflowId,
702
+ valid: issues === 0 && (!runtimeValidation?.executed || runtimeValidation.status === 'success'),
703
+ score,
704
+ nodeResults,
705
+ connectionResults,
706
+ credentialResults,
707
+ runtimeValidation,
708
+ summary: {
709
+ totalNodes: workflow.nodes.length,
710
+ validNodes,
711
+ totalConnections: Object.keys(workflow.connections).length,
712
+ validConnections,
713
+ issues,
714
+ warnings,
715
+ runtimeExecuted: runtimeValidation?.executed,
716
+ runtimePassed: runtimeValidation?.executed ?
717
+ runtimeValidation.status === 'success' && runtimeValidation.nodesFailed.length === 0 :
718
+ undefined,
719
+ },
720
+ };
721
+ // Store result
722
+ await this.storeTestResult(`node-validation:${workflowId}`, result);
723
+ // Emit event
724
+ this.emitEvent('node.validation.completed', {
725
+ workflowId,
726
+ valid: result.valid,
727
+ score: result.score,
728
+ issues: result.summary.issues,
729
+ runtimeExecuted: result.summary.runtimeExecuted,
730
+ runtimePassed: result.summary.runtimePassed,
731
+ });
732
+ return result;
733
+ }
734
+ /**
735
+ * Execute REAL runtime validation by actually running the workflow
736
+ * This catches issues that static analysis cannot find:
737
+ * - Credential authentication failures
738
+ * - API connectivity issues
739
+ * - Runtime type mismatches
740
+ * - External service availability
741
+ */
742
+ async executeRuntimeValidation(workflowId, testInput) {
743
+ const startTime = Date.now();
744
+ try {
745
+ // Execute the workflow
746
+ const execution = await this.executeWorkflow(workflowId, testInput);
747
+ // Wait for completion with timeout
748
+ const completedExecution = await this.waitForExecution(execution.id, 60000);
749
+ // Extract results
750
+ const nodesExecuted = this.extractExecutedNodes(completedExecution);
751
+ const errors = this.extractNodeErrors(completedExecution);
752
+ const nodesFailed = errors.map(e => e.nodeName);
753
+ return {
754
+ executed: true,
755
+ executionId: completedExecution.id,
756
+ status: completedExecution.status,
757
+ nodesExecuted,
758
+ nodesFailed,
759
+ errors,
760
+ duration: Date.now() - startTime,
761
+ };
762
+ }
763
+ catch (error) {
764
+ return {
765
+ executed: true,
766
+ nodesExecuted: [],
767
+ nodesFailed: [],
768
+ errors: [{
769
+ nodeName: 'workflow',
770
+ errorMessage: error instanceof Error ? error.message : String(error),
771
+ errorType: 'execution_error',
772
+ }],
773
+ duration: Date.now() - startTime,
774
+ };
775
+ }
776
+ }
777
+ /**
778
+ * Wait for workflow execution to complete
779
+ */
780
+ async waitForExecution(executionId, timeout) {
781
+ const startTime = Date.now();
782
+ while (Date.now() - startTime < timeout) {
783
+ const execution = await this.n8nClient.getExecution(executionId);
784
+ if (execution.finished) {
785
+ return execution;
786
+ }
787
+ await new Promise(resolve => setTimeout(resolve, 500));
788
+ }
789
+ return this.n8nClient.getExecution(executionId);
790
+ }
791
+ /**
792
+ * Extract list of executed nodes from execution data
793
+ */
794
+ extractExecutedNodes(execution) {
795
+ if (!execution.data?.resultData?.runData) {
796
+ return [];
797
+ }
798
+ return Object.keys(execution.data.resultData.runData);
799
+ }
800
+ /**
801
+ * Extract node errors from execution data
802
+ */
803
+ extractNodeErrors(execution) {
804
+ const errors = [];
805
+ if (!execution.data?.resultData?.runData) {
806
+ // Check for top-level error
807
+ if (execution.data?.resultData?.error) {
808
+ const error = execution.data.resultData.error;
809
+ errors.push({
810
+ nodeName: 'workflow',
811
+ errorMessage: typeof error === 'string' ? error : error.message || 'Unknown error',
812
+ errorType: 'workflow_error',
813
+ });
814
+ }
815
+ return errors;
816
+ }
817
+ const runData = execution.data.resultData.runData;
818
+ for (const [nodeName, nodeRuns] of Object.entries(runData)) {
819
+ if (Array.isArray(nodeRuns)) {
820
+ for (const run of nodeRuns) {
821
+ if (run.error) {
822
+ errors.push({
823
+ nodeName,
824
+ errorMessage: typeof run.error === 'string'
825
+ ? run.error
826
+ : run.error.message || 'Node execution failed',
827
+ errorType: run.error.name || 'node_error',
828
+ });
829
+ }
830
+ }
831
+ }
832
+ }
833
+ return errors;
834
+ }
835
+ /**
836
+ * Validate all nodes in workflow
837
+ */
838
+ async validateNodes(workflow, strictMode = false) {
839
+ const results = [];
840
+ for (const node of workflow.nodes) {
841
+ const issues = this.validateNode(node, strictMode);
842
+ results.push({
843
+ nodeId: node.id,
844
+ nodeName: node.name,
845
+ nodeType: node.type,
846
+ valid: issues.filter(i => i.severity === 'error').length === 0,
847
+ issues,
848
+ });
849
+ }
850
+ return results;
851
+ }
852
+ /**
853
+ * Validate single node
854
+ */
855
+ validateNode(node, strictMode) {
856
+ const issues = [];
857
+ // Basic structure validation
858
+ if (!node.id) {
859
+ issues.push({
860
+ severity: 'error',
861
+ code: 'MISSING_NODE_ID',
862
+ message: 'Node is missing ID',
863
+ node: node.name,
864
+ });
865
+ }
866
+ if (!node.type) {
867
+ issues.push({
868
+ severity: 'error',
869
+ code: 'MISSING_NODE_TYPE',
870
+ message: 'Node is missing type',
871
+ node: node.name,
872
+ });
873
+ }
874
+ if (!node.position || node.position.length !== 2) {
875
+ issues.push({
876
+ severity: 'warning',
877
+ code: 'INVALID_POSITION',
878
+ message: 'Node has invalid position',
879
+ node: node.name,
880
+ });
881
+ }
882
+ // Type-specific validation
883
+ const config = NODE_CONFIGS[node.type];
884
+ if (config) {
885
+ // Check required parameters
886
+ for (const param of config.requiredParams) {
887
+ if (!this.hasParameter(node, param)) {
888
+ issues.push({
889
+ severity: strictMode ? 'error' : 'warning',
890
+ code: 'MISSING_REQUIRED_PARAM',
891
+ message: `Missing required parameter: ${param}`,
892
+ node: node.name,
893
+ field: param,
894
+ suggestion: `Add the "${param}" parameter to this node`,
895
+ });
896
+ }
897
+ }
898
+ // Check credential requirement
899
+ if (config.requiresCredential && !node.credentials) {
900
+ issues.push({
901
+ severity: 'error',
902
+ code: 'MISSING_CREDENTIAL',
903
+ message: `Node requires credentials but none configured`,
904
+ node: node.name,
905
+ suggestion: `Configure ${config.credentialTypes?.join(' or ')} credentials`,
906
+ });
907
+ }
908
+ }
909
+ // Check for disabled nodes in active workflow
910
+ if (node.disabled) {
911
+ issues.push({
912
+ severity: 'info',
913
+ code: 'DISABLED_NODE',
914
+ message: 'Node is disabled',
915
+ node: node.name,
916
+ });
917
+ }
918
+ // Validate IF/Switch conditions
919
+ if (node.type === 'n8n-nodes-base.if' || node.type === 'n8n-nodes-base.switch') {
920
+ issues.push(...this.validateConditionalNode(node));
921
+ }
922
+ return issues;
923
+ }
924
+ /**
925
+ * Validate conditional nodes (IF/Switch)
926
+ */
927
+ validateConditionalNode(node) {
928
+ const issues = [];
929
+ if (node.type === 'n8n-nodes-base.if') {
930
+ const conditions = node.parameters.conditions;
931
+ if (!conditions) {
932
+ issues.push({
933
+ severity: 'error',
934
+ code: 'MISSING_CONDITIONS',
935
+ message: 'IF node has no conditions configured',
936
+ node: node.name,
937
+ });
938
+ }
939
+ else {
940
+ // Check condition structure
941
+ const hasValidConditions = Object.values(conditions).some(group => Array.isArray(group) && group.length > 0);
942
+ if (!hasValidConditions) {
943
+ issues.push({
944
+ severity: 'warning',
945
+ code: 'EMPTY_CONDITIONS',
946
+ message: 'IF node has empty conditions',
947
+ node: node.name,
948
+ });
949
+ }
950
+ }
951
+ }
952
+ if (node.type === 'n8n-nodes-base.switch') {
953
+ const rules = node.parameters.rules;
954
+ if (!rules || !Array.isArray(rules) || rules.length === 0) {
955
+ issues.push({
956
+ severity: 'error',
957
+ code: 'MISSING_RULES',
958
+ message: 'Switch node has no rules configured',
959
+ node: node.name,
960
+ });
961
+ }
962
+ }
963
+ return issues;
964
+ }
965
+ /**
966
+ * Validate connections between nodes
967
+ */
968
+ validateConnections(workflow) {
969
+ const results = [];
970
+ const nodeNames = new Set(workflow.nodes.map(n => n.name));
971
+ for (const [sourceName, connections] of Object.entries(workflow.connections)) {
972
+ const issues = [];
973
+ // Check source exists
974
+ if (!nodeNames.has(sourceName)) {
975
+ issues.push({
976
+ severity: 'error',
977
+ code: 'INVALID_SOURCE',
978
+ message: `Connection source "${sourceName}" does not exist`,
979
+ });
980
+ }
981
+ // Check each target
982
+ if (connections.main) {
983
+ for (let outputIndex = 0; outputIndex < connections.main.length; outputIndex++) {
984
+ const output = connections.main[outputIndex];
985
+ for (const conn of output) {
986
+ const targetIssues = [];
987
+ if (!nodeNames.has(conn.node)) {
988
+ targetIssues.push({
989
+ severity: 'error',
990
+ code: 'INVALID_TARGET',
991
+ message: `Connection target "${conn.node}" does not exist`,
992
+ });
993
+ }
994
+ // Check for self-references
995
+ if (conn.node === sourceName) {
996
+ targetIssues.push({
997
+ severity: 'warning',
998
+ code: 'SELF_REFERENCE',
999
+ message: 'Node connects to itself',
1000
+ node: sourceName,
1001
+ });
1002
+ }
1003
+ results.push({
1004
+ source: sourceName,
1005
+ target: conn.node,
1006
+ valid: targetIssues.filter(i => i.severity === 'error').length === 0,
1007
+ issues: targetIssues,
1008
+ });
1009
+ }
1010
+ }
1011
+ }
1012
+ }
1013
+ return results;
1014
+ }
1015
+ /**
1016
+ * Validate credential references
1017
+ */
1018
+ async validateCredentials(workflow) {
1019
+ const results = [];
1020
+ // Get available credentials
1021
+ let availableCredentials;
1022
+ try {
1023
+ const credentials = await this.n8nClient.listCredentials();
1024
+ availableCredentials = new Map(credentials.map(c => [c.id, true]));
1025
+ }
1026
+ catch {
1027
+ // If we can't fetch credentials, skip validation
1028
+ return results;
1029
+ }
1030
+ for (const node of workflow.nodes) {
1031
+ if (node.credentials) {
1032
+ for (const [credType, credRef] of Object.entries(node.credentials)) {
1033
+ const exists = availableCredentials.has(credRef.id);
1034
+ results.push({
1035
+ nodeId: node.id,
1036
+ nodeName: node.name,
1037
+ credentialType: credType,
1038
+ credentialId: credRef.id,
1039
+ valid: exists,
1040
+ exists,
1041
+ issue: exists ? undefined : `Credential "${credRef.name}" (${credRef.id}) not found`,
1042
+ });
1043
+ }
1044
+ }
1045
+ }
1046
+ return results;
1047
+ }
1048
+ /**
1049
+ * Check if node has a parameter (handles nested paths)
1050
+ */
1051
+ hasParameter(node, param) {
1052
+ const parts = param.split('.');
1053
+ let current = node.parameters;
1054
+ for (const part of parts) {
1055
+ if (current === null || current === undefined)
1056
+ return false;
1057
+ if (typeof current !== 'object')
1058
+ return false;
1059
+ current = current[part];
1060
+ }
1061
+ return current !== undefined && current !== null && current !== '';
1062
+ }
1063
+ /**
1064
+ * Get validation summary for a workflow
1065
+ */
1066
+ async getValidationSummary(workflowId) {
1067
+ const result = await this.validateWorkflow(workflowId);
1068
+ const recommendations = [];
1069
+ // Generate recommendations based on issues
1070
+ if (result.summary.issues > 0) {
1071
+ recommendations.push('Fix all error-level issues before deployment');
1072
+ }
1073
+ if (result.credentialResults.some(r => !r.valid)) {
1074
+ recommendations.push('Configure missing credentials');
1075
+ }
1076
+ const orphanNodes = result.nodeResults.filter(r => r.issues.some(i => i.code === 'ORPHAN_NODE'));
1077
+ if (orphanNodes.length > 0) {
1078
+ recommendations.push(`Connect or remove ${orphanNodes.length} orphan node(s)`);
1079
+ }
1080
+ return {
1081
+ valid: result.valid,
1082
+ score: result.score,
1083
+ issues: result.summary.issues,
1084
+ warnings: result.summary.warnings,
1085
+ recommendations,
1086
+ };
1087
+ }
1088
+ }
1089
+ exports.N8nNodeValidatorAgent = N8nNodeValidatorAgent;
1090
+ //# sourceMappingURL=N8nNodeValidatorAgent.js.map