@path58/n8n-mcp 0.1.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.
- package/AGENT_INSTALL.md +223 -0
- package/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/autofix/suggestion-fixers/deprecated-node-fixer.js +465 -0
- package/dist/autofix/suggestion-fixers/deprecated-node-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/fixer-registry.js +495 -0
- package/dist/autofix/suggestion-fixers/fixer-registry.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l1-structure-fixer.js +639 -0
- package/dist/autofix/suggestion-fixers/l1-structure-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l4-connection-fixer.js +449 -0
- package/dist/autofix/suggestion-fixers/l4-connection-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l5-parameter-fixer.js +575 -0
- package/dist/autofix/suggestion-fixers/l5-parameter-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l5-typeversion-fixer.js +431 -0
- package/dist/autofix/suggestion-fixers/l5-typeversion-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l5-webhook-path-fixer.js +356 -0
- package/dist/autofix/suggestion-fixers/l5-webhook-path-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l6-ai-tool-variant-fixer.js +618 -0
- package/dist/autofix/suggestion-fixers/l6-ai-tool-variant-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/l6-pattern-fixer.js +1475 -0
- package/dist/autofix/suggestion-fixers/l6-pattern-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/llm-fixer.js +716 -0
- package/dist/autofix/suggestion-fixers/llm-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/missing-credential-fixer.js +336 -0
- package/dist/autofix/suggestion-fixers/missing-credential-fixer.js.map +1 -0
- package/dist/autofix/suggestion-fixers/types.js +29 -0
- package/dist/autofix/suggestion-fixers/types.js.map +1 -0
- package/dist/autofix/suggestion-fixers/typo-fixer.js +197 -0
- package/dist/autofix/suggestion-fixers/typo-fixer.js.map +1 -0
- package/dist/classification/certification-engine.js +208 -0
- package/dist/classification/certification-engine.js.map +1 -0
- package/dist/classification/feedback-collector.js +516 -0
- package/dist/classification/feedback-collector.js.map +1 -0
- package/dist/classification/l5-parameter-analyzer.js +670 -0
- package/dist/classification/l5-parameter-analyzer.js.map +1 -0
- package/dist/classification/l6-graph-analyzer.js +613 -0
- package/dist/classification/l6-graph-analyzer.js.map +1 -0
- package/dist/classification/severity-classifier.js +237 -0
- package/dist/classification/severity-classifier.js.map +1 -0
- package/dist/config/env.js +280 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/env.schema.js +234 -0
- package/dist/config/env.schema.js.map +1 -0
- package/dist/config/scraperEnv.js +55 -0
- package/dist/config/scraperEnv.js.map +1 -0
- package/dist/db/postgresClient.js +38 -0
- package/dist/db/postgresClient.js.map +1 -0
- package/dist/db/scraperDb.js +6 -0
- package/dist/db/scraperDb.js.map +1 -0
- package/dist/db/scraperPostgresClient.js +118 -0
- package/dist/db/scraperPostgresClient.js.map +1 -0
- package/dist/db/validationRepository.js +55 -0
- package/dist/db/validationRepository.js.map +1 -0
- package/dist/db/validatorPostgresClient.js +248 -0
- package/dist/db/validatorPostgresClient.js.map +1 -0
- package/dist/db/workflowInstanceMappingRepository.js +128 -0
- package/dist/db/workflowInstanceMappingRepository.js.map +1 -0
- package/dist/errors/AppError.js +156 -0
- package/dist/errors/AppError.js.map +1 -0
- package/dist/errors/index.js +7 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/factory/error-to-problem-mappers.js +385 -0
- package/dist/factory/error-to-problem-mappers.js.map +1 -0
- package/dist/factory/gap-recorder.js +260 -0
- package/dist/factory/gap-recorder.js.map +1 -0
- package/dist/factory/problem-recorder.js +94 -0
- package/dist/factory/problem-recorder.js.map +1 -0
- package/dist/factory/warning-to-gap-mappers.js +493 -0
- package/dist/factory/warning-to-gap-mappers.js.map +1 -0
- package/dist/factory/workflow-normalizer.js +247 -0
- package/dist/factory/workflow-normalizer.js.map +1 -0
- package/dist/mcp/adapters/catalog.js +13 -0
- package/dist/mcp/adapters/catalog.js.map +1 -0
- package/dist/mcp/adapters/index.js +36 -0
- package/dist/mcp/adapters/index.js.map +1 -0
- package/dist/mcp/adapters/supabase-catalog.js +467 -0
- package/dist/mcp/adapters/supabase-catalog.js.map +1 -0
- package/dist/mcp/adapters/test-catalog-adapter.js +100 -0
- package/dist/mcp/adapters/test-catalog-adapter.js.map +1 -0
- package/dist/mcp/adapters/validation.js +258 -0
- package/dist/mcp/adapters/validation.js.map +1 -0
- package/dist/mcp/build-email-workflow.js +113 -0
- package/dist/mcp/build-email-workflow.js.map +1 -0
- package/dist/mcp/config.js +22 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/formatters/errors.js +217 -0
- package/dist/mcp/formatters/errors.js.map +1 -0
- package/dist/mcp/formatters/index.js +12 -0
- package/dist/mcp/formatters/index.js.map +1 -0
- package/dist/mcp/formatters/response.js +141 -0
- package/dist/mcp/formatters/response.js.map +1 -0
- package/dist/mcp/quick-test.js +33 -0
- package/dist/mcp/quick-test.js.map +1 -0
- package/dist/mcp/server.js +70 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/test-mcp-error.js +81 -0
- package/dist/mcp/test-mcp-error.js.map +1 -0
- package/dist/mcp/test-mcp.js +80 -0
- package/dist/mcp/test-mcp.js.map +1 -0
- package/dist/mcp/tools/fixes/expression-fixes.js +166 -0
- package/dist/mcp/tools/fixes/expression-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/flow-fixes.js +155 -0
- package/dist/mcp/tools/fixes/flow-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/index.js +91 -0
- package/dist/mcp/tools/fixes/index.js.map +1 -0
- package/dist/mcp/tools/fixes/node-fixes.js +233 -0
- package/dist/mcp/tools/fixes/node-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/parameter-fixes.js +277 -0
- package/dist/mcp/tools/fixes/parameter-fixes.js.map +1 -0
- package/dist/mcp/tools/fixes/types.js +10 -0
- package/dist/mcp/tools/fixes/types.js.map +1 -0
- package/dist/mcp/tools/handlers/check-parameter.js +300 -0
- package/dist/mcp/tools/handlers/check-parameter.js.map +1 -0
- package/dist/mcp/tools/handlers/find-similar-pattern.js +121 -0
- package/dist/mcp/tools/handlers/find-similar-pattern.js.map +1 -0
- package/dist/mcp/tools/handlers/get-node-info.js +131 -0
- package/dist/mcp/tools/handlers/get-node-info.js.map +1 -0
- package/dist/mcp/tools/handlers/get-operation-schema.js +141 -0
- package/dist/mcp/tools/handlers/get-operation-schema.js.map +1 -0
- package/dist/mcp/tools/handlers/list-nodes.js +126 -0
- package/dist/mcp/tools/handlers/list-nodes.js.map +1 -0
- package/dist/mcp/tools/handlers/list-operations.js +138 -0
- package/dist/mcp/tools/handlers/list-operations.js.map +1 -0
- package/dist/mcp/tools/handlers/suggest-fix.js +120 -0
- package/dist/mcp/tools/handlers/suggest-fix.js.map +1 -0
- package/dist/mcp/tools/handlers/validate-workflow.js +92 -0
- package/dist/mcp/tools/handlers/validate-workflow.js.map +1 -0
- package/dist/mcp/tools/index.js +190 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/schemas.js +195 -0
- package/dist/mcp/tools/schemas.js.map +1 -0
- package/dist/mcp/tools/validate.js +95 -0
- package/dist/mcp/tools/validate.js.map +1 -0
- package/dist/mcp/types/mcp.js +7 -0
- package/dist/mcp/types/mcp.js.map +1 -0
- package/dist/mcp/utils/timeout.js +78 -0
- package/dist/mcp/utils/timeout.js.map +1 -0
- package/dist/services/BatchProcessor.js +433 -0
- package/dist/services/BatchProcessor.js.map +1 -0
- package/dist/services/CheckpointManager.js +281 -0
- package/dist/services/CheckpointManager.js.map +1 -0
- package/dist/services/CostCalculator.js +211 -0
- package/dist/services/CostCalculator.js.map +1 -0
- package/dist/services/EmbeddingCache.js +68 -0
- package/dist/services/EmbeddingCache.js.map +1 -0
- package/dist/services/EmbeddingService.js +143 -0
- package/dist/services/EmbeddingService.js.map +1 -0
- package/dist/services/RankingService.js +81 -0
- package/dist/services/RankingService.js.map +1 -0
- package/dist/services/RedisCache.js +376 -0
- package/dist/services/RedisCache.js.map +1 -0
- package/dist/services/RedisCatalogCache.js +680 -0
- package/dist/services/RedisCatalogCache.js.map +1 -0
- package/dist/services/ResumeManager.js +252 -0
- package/dist/services/ResumeManager.js.map +1 -0
- package/dist/services/SearchService.js +282 -0
- package/dist/services/SearchService.js.map +1 -0
- package/dist/services/SemanticCatalogSearch.js +405 -0
- package/dist/services/SemanticCatalogSearch.js.map +1 -0
- package/dist/services/ValidationCache.js +157 -0
- package/dist/services/ValidationCache.js.map +1 -0
- package/dist/services/WorkflowPipelineService.js +1997 -0
- package/dist/services/WorkflowPipelineService.js.map +1 -0
- package/dist/services/catalog/index.js +34 -0
- package/dist/services/catalog/index.js.map +1 -0
- package/dist/services/catalog/interfaces.js +17 -0
- package/dist/services/catalog/interfaces.js.map +1 -0
- package/dist/services/catalog/loaders.js +169 -0
- package/dist/services/catalog/loaders.js.map +1 -0
- package/dist/services/catalog/types.js +138 -0
- package/dist/services/catalog/types.js.map +1 -0
- package/dist/services/documentation-normalization/docUrlUtils.js +88 -0
- package/dist/services/documentation-normalization/docUrlUtils.js.map +1 -0
- package/dist/services/error-quality/ErrorQualityService.js +262 -0
- package/dist/services/error-quality/ErrorQualityService.js.map +1 -0
- package/dist/services/error-quality/analyzers/CredentialAnalyzer.js +260 -0
- package/dist/services/error-quality/analyzers/CredentialAnalyzer.js.map +1 -0
- package/dist/services/error-quality/analyzers/IssuePredictor.js +380 -0
- package/dist/services/error-quality/analyzers/IssuePredictor.js.map +1 -0
- package/dist/services/error-quality/analyzers/MockCoverageAnalyzer.js +267 -0
- package/dist/services/error-quality/analyzers/MockCoverageAnalyzer.js.map +1 -0
- package/dist/services/error-quality/data/ErrorPatternSeeder.js +963 -0
- package/dist/services/error-quality/data/ErrorPatternSeeder.js.map +1 -0
- package/dist/services/error-quality/index.js +25 -0
- package/dist/services/error-quality/index.js.map +1 -0
- package/dist/services/error-quality/reports/ReportGenerator.js +343 -0
- package/dist/services/error-quality/reports/ReportGenerator.js.map +1 -0
- package/dist/services/error-quality/taxonomy/ErrorTaxonomy.js +698 -0
- package/dist/services/error-quality/taxonomy/ErrorTaxonomy.js.map +1 -0
- package/dist/services/error-quality/types.js +11 -0
- package/dist/services/error-quality/types.js.map +1 -0
- package/dist/services/progress/ProgressTracker.js +288 -0
- package/dist/services/progress/ProgressTracker.js.map +1 -0
- package/dist/services/progress/formatters.js +122 -0
- package/dist/services/progress/formatters.js.map +1 -0
- package/dist/services/progress/index.js +36 -0
- package/dist/services/progress/index.js.map +1 -0
- package/dist/services/progress/types.js +7 -0
- package/dist/services/progress/types.js.map +1 -0
- package/dist/services/search/embeddingGenerator.js +112 -0
- package/dist/services/search/embeddingGenerator.js.map +1 -0
- package/dist/types/aiCapabilities.js +7 -0
- package/dist/types/aiCapabilities.js.map +1 -0
- package/dist/types/aiConfigSchema.js +7 -0
- package/dist/types/aiConfigSchema.js.map +1 -0
- package/dist/utils/bannerLogger.js +186 -0
- package/dist/utils/bannerLogger.js.map +1 -0
- package/dist/utils/bannerService.js +23 -0
- package/dist/utils/bannerService.js.map +1 -0
- package/dist/utils/bannerServiceAdapter.js +54 -0
- package/dist/utils/bannerServiceAdapter.js.map +1 -0
- package/dist/utils/batchLogger.js +171 -0
- package/dist/utils/batchLogger.js.map +1 -0
- package/dist/utils/bottomStickyBanner.js +239 -0
- package/dist/utils/bottomStickyBanner.js.map +1 -0
- package/dist/utils/credentialMatcher.js +206 -0
- package/dist/utils/credentialMatcher.js.map +1 -0
- package/dist/utils/credentialNormalizer.js +442 -0
- package/dist/utils/credentialNormalizer.js.map +1 -0
- package/dist/utils/integratedBannerLogger.js +59 -0
- package/dist/utils/integratedBannerLogger.js.map +1 -0
- package/dist/utils/n8nSourceGit.js +195 -0
- package/dist/utils/n8nSourceGit.js.map +1 -0
- package/dist/utils/nodeTypeNormalizer.js +131 -0
- package/dist/utils/nodeTypeNormalizer.js.map +1 -0
- package/dist/utils/openaiClient.js +397 -0
- package/dist/utils/openaiClient.js.map +1 -0
- package/dist/utils/productionLogger.js +16 -0
- package/dist/utils/productionLogger.js.map +1 -0
- package/dist/utils/progressBarBanner.js +132 -0
- package/dist/utils/progressBarBanner.js.map +1 -0
- package/dist/utils/scriptHeartbeat.js +117 -0
- package/dist/utils/scriptHeartbeat.js.map +1 -0
- package/dist/utils/scriptLogger.js +125 -0
- package/dist/utils/scriptLogger.js.map +1 -0
- package/dist/utils/scriptRunner.js +95 -0
- package/dist/utils/scriptRunner.js.map +1 -0
- package/dist/utils/scriptTimeout.js +128 -0
- package/dist/utils/scriptTimeout.js.map +1 -0
- package/dist/utils/scriptWrapper.js +219 -0
- package/dist/utils/scriptWrapper.js.map +1 -0
- package/dist/utils/stickyBanner.js +226 -0
- package/dist/utils/stickyBanner.js.map +1 -0
- package/dist/utils/terminalSpinner.js +97 -0
- package/dist/utils/terminalSpinner.js.map +1 -0
- package/dist/utils/threeLineBanner.js +427 -0
- package/dist/utils/threeLineBanner.js.map +1 -0
- package/dist/utils/validatorCheckpointManager.js +170 -0
- package/dist/utils/validatorCheckpointManager.js.map +1 -0
- package/dist/utils/validatorConnectionManager.js +124 -0
- package/dist/utils/validatorConnectionManager.js.map +1 -0
- package/dist/validation/catalog.js +56 -0
- package/dist/validation/catalog.js.map +1 -0
- package/dist/validation/config/deprecated-nodes.js +234 -0
- package/dist/validation/config/deprecated-nodes.js.map +1 -0
- package/dist/validation/config/l6-severity.js +227 -0
- package/dist/validation/config/l6-severity.js.map +1 -0
- package/dist/validation/config/terminal-nodes.js +132 -0
- package/dist/validation/config/terminal-nodes.js.map +1 -0
- package/dist/validation/config/unreachable-nodes.js +67 -0
- package/dist/validation/config/unreachable-nodes.js.map +1 -0
- package/dist/validation/core.js +47 -0
- package/dist/validation/core.js.map +1 -0
- package/dist/validation/docExtraction.js +12 -0
- package/dist/validation/docExtraction.js.map +1 -0
- package/dist/validation/dryRunMockRunner.js +128 -0
- package/dist/validation/dryRunMockRunner.js.map +1 -0
- package/dist/validation/fixtureEngine.js +61 -0
- package/dist/validation/fixtureEngine.js.map +1 -0
- package/dist/validation/index.js +15 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/k-levels/k2-blockers.js +222 -0
- package/dist/validation/k-levels/k2-blockers.js.map +1 -0
- package/dist/validation/l1-structure.js +296 -0
- package/dist/validation/l1-structure.js.map +1 -0
- package/dist/validation/l2-nodes.js +282 -0
- package/dist/validation/l2-nodes.js.map +1 -0
- package/dist/validation/l3-credentials.js +322 -0
- package/dist/validation/l3-credentials.js.map +1 -0
- package/dist/validation/l4-connections.js +698 -0
- package/dist/validation/l4-connections.js.map +1 -0
- package/dist/validation/l5-parameters.js +803 -0
- package/dist/validation/l5-parameters.js.map +1 -0
- package/dist/validation/l6-checks/ai-tool-variants.js +407 -0
- package/dist/validation/l6-checks/ai-tool-variants.js.map +1 -0
- package/dist/validation/l6-checks/catalog-checks.js +260 -0
- package/dist/validation/l6-checks/catalog-checks.js.map +1 -0
- package/dist/validation/l6-checks/data-contracts.js +197 -0
- package/dist/validation/l6-checks/data-contracts.js.map +1 -0
- package/dist/validation/l6-checks/deprecation.js +133 -0
- package/dist/validation/l6-checks/deprecation.js.map +1 -0
- package/dist/validation/l6-checks/error-handling.js +193 -0
- package/dist/validation/l6-checks/error-handling.js.map +1 -0
- package/dist/validation/l6-checks/expression-syntax.js +387 -0
- package/dist/validation/l6-checks/expression-syntax.js.map +1 -0
- package/dist/validation/l6-checks/flow-integrity.js +504 -0
- package/dist/validation/l6-checks/flow-integrity.js.map +1 -0
- package/dist/validation/l6-checks/index.js +106 -0
- package/dist/validation/l6-checks/index.js.map +1 -0
- package/dist/validation/l6-checks/loops.js +370 -0
- package/dist/validation/l6-checks/loops.js.map +1 -0
- package/dist/validation/l6-checks/performance.js +182 -0
- package/dist/validation/l6-checks/performance.js.map +1 -0
- package/dist/validation/l6-checks/security.js +273 -0
- package/dist/validation/l6-checks/security.js.map +1 -0
- package/dist/validation/l6-patterns.js +472 -0
- package/dist/validation/l6-patterns.js.map +1 -0
- package/dist/validation/mockLevelResolver.js +95 -0
- package/dist/validation/mockLevelResolver.js.map +1 -0
- package/dist/validation/n8nApiClient.js +21 -0
- package/dist/validation/n8nApiClient.js.map +1 -0
- package/dist/validation/n8nCli.js +87 -0
- package/dist/validation/n8nCli.js.map +1 -0
- package/dist/validation/types.js +8 -0
- package/dist/validation/types.js.map +1 -0
- package/dist/validation/usageStats.js +82 -0
- package/dist/validation/usageStats.js.map +1 -0
- package/package.json +274 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L6 Loop Detection Checks
|
|
3
|
+
*
|
|
4
|
+
* RAG-2.2.77: L6 New Pattern Checks
|
|
5
|
+
* Created: 2026-01-17
|
|
6
|
+
* Updated: 2026-01-22 (RAG-2.2.92.10: Add pattern detection for intentional loops)
|
|
7
|
+
*
|
|
8
|
+
* Validates workflow graph for circular references (infinite loops):
|
|
9
|
+
* - CIRCULAR_REFERENCE: Cycle detected in workflow graph
|
|
10
|
+
*
|
|
11
|
+
* Uses depth-first search (DFS) with recursion stack tracking
|
|
12
|
+
* to detect cycles in the directed graph of workflow connections.
|
|
13
|
+
*
|
|
14
|
+
* RAG-2.2.92.10: Now applies the same pattern detection logic as L4 to filter out
|
|
15
|
+
* intentional iteration patterns (879 L6_CIRCULAR_REFERENCE warnings were false positives).
|
|
16
|
+
*/
|
|
17
|
+
import { getL6Severity, blocksCertification } from '../config/l6-severity.js';
|
|
18
|
+
/** Intentional loop node types that create valid cycles */
|
|
19
|
+
const INTENTIONAL_LOOP_TYPES = new Set([
|
|
20
|
+
'n8n-nodes-base.splitInBatches',
|
|
21
|
+
'n8n-nodes-base.loop',
|
|
22
|
+
]);
|
|
23
|
+
/** Node types that indicate valid polling/retry patterns */
|
|
24
|
+
const POLLING_RETRY_NODE_TYPES = new Set([
|
|
25
|
+
'n8n-nodes-base.wait',
|
|
26
|
+
'n8n-nodes-base.if',
|
|
27
|
+
'n8n-nodes-base.switch',
|
|
28
|
+
]);
|
|
29
|
+
/** Node types that indicate valid conversational/iterative patterns */
|
|
30
|
+
const CONVERSATIONAL_NODE_TYPES = new Set([
|
|
31
|
+
'@n8n/n8n-nodes-langchain.agent',
|
|
32
|
+
'n8n-nodes-base.formTrigger',
|
|
33
|
+
'n8n-nodes-base.webhook',
|
|
34
|
+
]);
|
|
35
|
+
/** Node types used for code-based iteration control */
|
|
36
|
+
const CODE_ITERATION_NODE_TYPES = new Set([
|
|
37
|
+
'n8n-nodes-base.code',
|
|
38
|
+
'n8n-nodes-base.set',
|
|
39
|
+
]);
|
|
40
|
+
/**
|
|
41
|
+
* Keywords indicating intentional iteration patterns
|
|
42
|
+
* (from L4_ITERATIVE_LOOP_PATTERNS.md)
|
|
43
|
+
*/
|
|
44
|
+
const ITERATION_KEYWORDS = [
|
|
45
|
+
// Loop control keywords
|
|
46
|
+
'loop', 'vars', 'iteration', 'step', 'next', 'retry', 'cycle',
|
|
47
|
+
// Validation keywords
|
|
48
|
+
'check', 'validate', 'verify', 'status', 'poll',
|
|
49
|
+
// Content generation keywords
|
|
50
|
+
'generate', 'create', 'planner',
|
|
51
|
+
// Human-in-the-loop keywords
|
|
52
|
+
'approval', 'review', 'feedback', 'revision', 'human',
|
|
53
|
+
// Router/command keywords
|
|
54
|
+
'router', 'responder', 'command',
|
|
55
|
+
// Data processing keywords (common in ETL/sync workflows)
|
|
56
|
+
'refresh', 'token', 'download', 'upload', 'load', 'merge', 'extract',
|
|
57
|
+
// Conditional loop keywords
|
|
58
|
+
'exists', 'invalid', 'complete', 'loaded', 'open', 'all', 'finished',
|
|
59
|
+
// Pagination/cursor keywords
|
|
60
|
+
'page', 'cursor', 'increment', 'more', 'list', 'get',
|
|
61
|
+
// Sync/update keywords
|
|
62
|
+
'sync', 'update', 'clear', 'duplicate', 'rename', 'set',
|
|
63
|
+
// Automation/deployment keywords
|
|
64
|
+
'docker', 'compose', 'pull', 'image', 'deploy', 'approve', 'notif',
|
|
65
|
+
// Audio/voice processing keywords
|
|
66
|
+
'voice', 'audio', 'fetch', 'text', 'speech', 'tts',
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Build a map of node names to their types
|
|
70
|
+
*/
|
|
71
|
+
function buildNodeTypeMap(workflow) {
|
|
72
|
+
const map = new Map();
|
|
73
|
+
if (workflow.nodes && Array.isArray(workflow.nodes)) {
|
|
74
|
+
for (const node of workflow.nodes) {
|
|
75
|
+
map.set(node.name, node.type);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return map;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Check if cycle contains a Wait/delay node
|
|
82
|
+
*/
|
|
83
|
+
function hasWaitNode(cycleNodeTypes) {
|
|
84
|
+
return cycleNodeTypes.includes('n8n-nodes-base.wait');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if cycle contains If/Switch conditional nodes
|
|
88
|
+
*/
|
|
89
|
+
function hasConditionalNode(cycleNodeTypes) {
|
|
90
|
+
return cycleNodeTypes.some((type) => type === 'n8n-nodes-base.if' || type === 'n8n-nodes-base.switch');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if cycle represents a status polling pattern
|
|
94
|
+
*/
|
|
95
|
+
function isStatusPollingPattern(cycleLower, hasWait) {
|
|
96
|
+
if (!hasWait)
|
|
97
|
+
return false;
|
|
98
|
+
const statusKeywords = ['status', 'check', 'verify', 'complete', 'ready', 'progress'];
|
|
99
|
+
return statusKeywords.some((kw) => cycleLower.includes(kw));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Check if cycle represents a result polling pattern
|
|
103
|
+
*/
|
|
104
|
+
function isResultPollingPattern(cycleLower, hasWait) {
|
|
105
|
+
if (!hasWait)
|
|
106
|
+
return false;
|
|
107
|
+
return cycleLower.includes('get results') ||
|
|
108
|
+
cycleLower.includes('get result') ||
|
|
109
|
+
cycleLower.includes('get status');
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if cycle represents an AI agent conversational loop
|
|
113
|
+
*/
|
|
114
|
+
function isAgentLoopPattern(cycleNodeTypes, cycleLower, cycleLength) {
|
|
115
|
+
if (cycleLength < 3)
|
|
116
|
+
return false;
|
|
117
|
+
return cycleNodeTypes.some((type) => type === '@n8n/n8n-nodes-langchain.agent' || type?.includes('agent')) || cycleLower.includes('agent');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check if cycle represents a form validation retry pattern
|
|
121
|
+
*/
|
|
122
|
+
function isFormRetryPattern(cycleNodeTypes, cycleLower) {
|
|
123
|
+
const hasFormNode = cycleNodeTypes.some((type) => type === 'n8n-nodes-base.formTrigger' || type === 'n8n-nodes-base.webhook');
|
|
124
|
+
if (!hasFormNode)
|
|
125
|
+
return false;
|
|
126
|
+
const formKeywords = ['form', 'validation', 'retry', 'reenter', 'correct'];
|
|
127
|
+
return formKeywords.some((kw) => cycleLower.includes(kw));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if cycle represents a code-based iteration pattern
|
|
131
|
+
*
|
|
132
|
+
* These are intentional loops that use IF/Switch + Code/Set nodes instead of
|
|
133
|
+
* explicit loop nodes. Common in n8n.io published workflows.
|
|
134
|
+
*
|
|
135
|
+
* See: docs/validation/levels/l4/L4_ITERATIVE_LOOP_PATTERNS.md
|
|
136
|
+
*/
|
|
137
|
+
function isCodeBasedIterationPattern(cycle, nodeTypeMap) {
|
|
138
|
+
const cycleNodeTypes = cycle.map((name) => nodeTypeMap.get(name)).filter(Boolean);
|
|
139
|
+
const cycleLower = cycle.join(' → ').toLowerCase();
|
|
140
|
+
// Pattern 1: Has IF/Switch node + iteration keywords
|
|
141
|
+
const hasIfNode = cycleNodeTypes.some((t) => t === 'n8n-nodes-base.if' || t === 'n8n-nodes-base.switch');
|
|
142
|
+
const hasIterationKeyword = ITERATION_KEYWORDS.some((kw) => cycleLower.includes(kw));
|
|
143
|
+
if (hasIfNode && hasIterationKeyword) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
// Pattern 2: Has Code/Set nodes for loop control (vars pattern)
|
|
147
|
+
const hasCodeIteration = cycleNodeTypes.some((t) => CODE_ITERATION_NODE_TYPES.has(t));
|
|
148
|
+
const hasVarsPattern = cycleLower.includes('vars') || cycleLower.includes('parameters');
|
|
149
|
+
if (hasCodeIteration && hasVarsPattern) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
// Pattern 3: Status polling pattern (Get + Check/Status + IF)
|
|
153
|
+
const hasGetAndCheck = cycleLower.includes('get') &&
|
|
154
|
+
(cycleLower.includes('status') || cycleLower.includes('check'));
|
|
155
|
+
if (hasGetAndCheck && hasIfNode) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
// Pattern 4: Self-loop (same node name repeated) - often Airtable/table patterns
|
|
159
|
+
// Example: "Table: Tools → Table: Tools"
|
|
160
|
+
if (cycle.length === 2 && cycle[0] === cycle[cycle.length - 1]) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
// Pattern 5: AI/LLM chain patterns
|
|
164
|
+
const hasAiChain = cycleLower.includes('chain') ||
|
|
165
|
+
cycleLower.includes('summariz') ||
|
|
166
|
+
cycleLower.includes('ai ') ||
|
|
167
|
+
cycleLower.includes('llm') ||
|
|
168
|
+
cycleLower.includes('gpt');
|
|
169
|
+
if (hasAiChain) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
// Pattern 6: Any cycle with IF node (conservative fallback for published n8n.io workflows)
|
|
173
|
+
// These are almost always intentional - IF nodes control loop termination
|
|
174
|
+
if (hasIfNode) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if a cycle is a valid polling/retry pattern
|
|
181
|
+
*/
|
|
182
|
+
function isPollingOrRetryPattern(cycle, nodeTypeMap) {
|
|
183
|
+
const cycleLower = cycle.join(' → ').toLowerCase();
|
|
184
|
+
const cycleNodeTypes = cycle.map((name) => nodeTypeMap.get(name)).filter(Boolean);
|
|
185
|
+
const hasWait = hasWaitNode(cycleNodeTypes);
|
|
186
|
+
return (isStatusPollingPattern(cycleLower, hasWait) ||
|
|
187
|
+
(hasConditionalNode(cycleNodeTypes) && hasWait) ||
|
|
188
|
+
isResultPollingPattern(cycleLower, hasWait) ||
|
|
189
|
+
hasWait ||
|
|
190
|
+
isAgentLoopPattern(cycleNodeTypes, cycleLower, cycle.length) ||
|
|
191
|
+
isFormRetryPattern(cycleNodeTypes, cycleLower) ||
|
|
192
|
+
isCodeBasedIterationPattern(cycle, nodeTypeMap));
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Check if a cycle is an intentional loop pattern
|
|
196
|
+
*
|
|
197
|
+
* RAG-2.2.92.10: Apply same logic as L4 to filter out intentional loops.
|
|
198
|
+
* Returns true if the cycle should be SKIPPED (not reported as an error).
|
|
199
|
+
*/
|
|
200
|
+
function isIntentionalLoopPattern(cycle, nodeTypeMap) {
|
|
201
|
+
// Check for explicit loop nodes first
|
|
202
|
+
for (const nodeName of cycle) {
|
|
203
|
+
const nodeType = nodeTypeMap.get(nodeName);
|
|
204
|
+
if (nodeType && INTENTIONAL_LOOP_TYPES.has(nodeType)) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Check for polling/retry/conversational patterns
|
|
209
|
+
for (const nodeName of cycle) {
|
|
210
|
+
const nodeType = nodeTypeMap.get(nodeName);
|
|
211
|
+
if (nodeType && (POLLING_RETRY_NODE_TYPES.has(nodeType) || CONVERSATIONAL_NODE_TYPES.has(nodeType))) {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// Check for code-based iteration patterns
|
|
216
|
+
if (isPollingOrRetryPattern(cycle, nodeTypeMap)) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get outgoing connection target node names from a source node
|
|
223
|
+
* @param nodeName - Source node name
|
|
224
|
+
* @param workflow - Workflow to analyze
|
|
225
|
+
* @returns Array of target node names
|
|
226
|
+
*/
|
|
227
|
+
function getOutgoingConnections(nodeName, workflow) {
|
|
228
|
+
const targets = [];
|
|
229
|
+
const outgoing = workflow.connections?.[nodeName];
|
|
230
|
+
if (!outgoing) {
|
|
231
|
+
return targets;
|
|
232
|
+
}
|
|
233
|
+
for (const outputType of Object.keys(outgoing)) {
|
|
234
|
+
const connections = outgoing[outputType];
|
|
235
|
+
if (!connections || !Array.isArray(connections)) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
for (const connectionGroup of connections) {
|
|
239
|
+
if (Array.isArray(connectionGroup)) {
|
|
240
|
+
for (const connection of connectionGroup) {
|
|
241
|
+
if (connection && typeof connection === 'object' && connection.node) {
|
|
242
|
+
targets.push(connection.node);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else if (connectionGroup && typeof connectionGroup === 'object' && 'node' in connectionGroup) {
|
|
247
|
+
const conn = connectionGroup;
|
|
248
|
+
if (typeof conn.node === 'string') {
|
|
249
|
+
targets.push(conn.node);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return targets;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Check for circular references (infinite loops) in workflow graph
|
|
258
|
+
*
|
|
259
|
+
* Uses DFS with recursion stack tracking to detect cycles.
|
|
260
|
+
* Reports all nodes involved in cycles.
|
|
261
|
+
*
|
|
262
|
+
* RAG-2.2.92.10: Now filters out intentional loop patterns using the same
|
|
263
|
+
* detection logic as L4. Intentional patterns include:
|
|
264
|
+
* - Explicit loop nodes (SplitInBatches, Loop)
|
|
265
|
+
* - Polling/retry patterns (Wait + If/Switch)
|
|
266
|
+
* - AI agent conversational loops
|
|
267
|
+
* - Code-based iteration patterns (IF + iteration keywords)
|
|
268
|
+
*
|
|
269
|
+
* @param context - L6 validation context
|
|
270
|
+
* @returns Array of L6Error for each cycle detected (excluding intentional patterns)
|
|
271
|
+
*/
|
|
272
|
+
export function checkCircularReferences(context) {
|
|
273
|
+
const { workflow } = context;
|
|
274
|
+
const errors = [];
|
|
275
|
+
// Guard: Ensure workflow.nodes exists
|
|
276
|
+
if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
|
|
277
|
+
return errors;
|
|
278
|
+
}
|
|
279
|
+
// RAG-2.2.92.10: Build node type map for pattern detection
|
|
280
|
+
const nodeTypeMap = buildNodeTypeMap(workflow);
|
|
281
|
+
const visited = new Set();
|
|
282
|
+
const recursionStack = new Set();
|
|
283
|
+
const reportedCycles = new Set(); // Avoid duplicate cycle reports
|
|
284
|
+
/**
|
|
285
|
+
* Depth-first search to detect cycles
|
|
286
|
+
* @param nodeName - Current node being visited
|
|
287
|
+
* @param path - Path of nodes visited to reach current node
|
|
288
|
+
*/
|
|
289
|
+
function dfs(nodeName, path) {
|
|
290
|
+
// If node is in recursion stack, we found a cycle
|
|
291
|
+
if (recursionStack.has(nodeName)) {
|
|
292
|
+
const cycleStart = path.indexOf(nodeName);
|
|
293
|
+
const cycle = path.slice(cycleStart);
|
|
294
|
+
// Create unique key for this cycle to avoid duplicates
|
|
295
|
+
const cycleKey = [...cycle].sort().join('->');
|
|
296
|
+
if (reportedCycles.has(cycleKey)) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
reportedCycles.add(cycleKey);
|
|
300
|
+
// RAG-2.2.92.10: Skip intentional loop patterns
|
|
301
|
+
if (isIntentionalLoopPattern(cycle, nodeTypeMap)) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const code = 'CIRCULAR_REFERENCE';
|
|
305
|
+
errors.push({
|
|
306
|
+
code: 'CIRCULAR_REFERENCE',
|
|
307
|
+
message: `Circular reference detected: ${cycle.join(' → ')} → ${nodeName}`,
|
|
308
|
+
path: `workflow.connections`,
|
|
309
|
+
node_name: nodeName,
|
|
310
|
+
severity: getL6Severity(code),
|
|
311
|
+
blocks_certification: blocksCertification(code),
|
|
312
|
+
details: {
|
|
313
|
+
cycle_nodes: cycle,
|
|
314
|
+
cycle_length: cycle.length,
|
|
315
|
+
},
|
|
316
|
+
suggested_fix: {
|
|
317
|
+
id: `fix-circular-${nodeName}-${Date.now()}`,
|
|
318
|
+
fix_type: 'remove_connection',
|
|
319
|
+
confidence: 0.7,
|
|
320
|
+
auto_applicable: false,
|
|
321
|
+
description: `Remove one connection to break the cycle: ${cycle.join(' → ')}`,
|
|
322
|
+
target_node: nodeName,
|
|
323
|
+
patch: {},
|
|
324
|
+
context: {
|
|
325
|
+
cycle_nodes: cycle,
|
|
326
|
+
suggested_break_point: cycle[cycle.length - 1], // Last node before cycle repeats
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
// If already fully visited, skip
|
|
333
|
+
if (visited.has(nodeName)) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// Mark as visiting (in recursion stack)
|
|
337
|
+
visited.add(nodeName);
|
|
338
|
+
recursionStack.add(nodeName);
|
|
339
|
+
// Visit all connected nodes
|
|
340
|
+
const connections = getOutgoingConnections(nodeName, workflow);
|
|
341
|
+
for (const targetNode of connections) {
|
|
342
|
+
dfs(targetNode, [...path, nodeName]);
|
|
343
|
+
}
|
|
344
|
+
// Remove from recursion stack when done
|
|
345
|
+
recursionStack.delete(nodeName);
|
|
346
|
+
}
|
|
347
|
+
// Start DFS from all nodes to handle disconnected subgraphs
|
|
348
|
+
for (const node of workflow.nodes) {
|
|
349
|
+
if (!visited.has(node.name)) {
|
|
350
|
+
dfs(node.name, []);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return errors;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Run all loop detection checks
|
|
357
|
+
*
|
|
358
|
+
* @param context - L6 validation context
|
|
359
|
+
* @returns Object containing errors and warnings
|
|
360
|
+
*/
|
|
361
|
+
export async function checkLoops(context) {
|
|
362
|
+
const startTime = performance.now();
|
|
363
|
+
const circularErrors = checkCircularReferences(context);
|
|
364
|
+
const duration = performance.now() - startTime;
|
|
365
|
+
return {
|
|
366
|
+
errors: circularErrors,
|
|
367
|
+
warnings: [], // No loop-related warnings currently
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
//# sourceMappingURL=loops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loops.js","sourceRoot":"","sources":["../../../src/validation/l6-checks/loops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L6 Performance Checks
|
|
3
|
+
*
|
|
4
|
+
* RAG-2.2.77: L6 New Pattern Checks
|
|
5
|
+
* Created: 2026-01-17
|
|
6
|
+
*
|
|
7
|
+
* Validates workflow performance characteristics:
|
|
8
|
+
* - OVERSIZED_WORKFLOW: Workflow has excessive number of nodes (50+)
|
|
9
|
+
* - EXCESSIVE_RETRY: Node has excessive retry configuration (>10)
|
|
10
|
+
*
|
|
11
|
+
* These are warnings that don't block certification but flag
|
|
12
|
+
* potential performance and maintainability issues.
|
|
13
|
+
*/
|
|
14
|
+
import { getL6Severity, blocksCertification } from '../config/l6-severity.js';
|
|
15
|
+
/**
|
|
16
|
+
* Workflow size thresholds
|
|
17
|
+
*/
|
|
18
|
+
const SIZE_THRESHOLDS = {
|
|
19
|
+
/** Warning threshold - workflow is getting large */
|
|
20
|
+
warning: 50,
|
|
21
|
+
/** Critical threshold - workflow is too large, suggest splitting */
|
|
22
|
+
critical: 100,
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Maximum reasonable retry count
|
|
26
|
+
*/
|
|
27
|
+
const MAX_REASONABLE_RETRIES = 10;
|
|
28
|
+
/**
|
|
29
|
+
* Check for oversized workflows (50+ nodes)
|
|
30
|
+
*
|
|
31
|
+
* Large workflows can impact:
|
|
32
|
+
* - Performance during execution
|
|
33
|
+
* - Maintainability and debugging
|
|
34
|
+
* - n8n editor responsiveness
|
|
35
|
+
*
|
|
36
|
+
* @param context - L6 validation context
|
|
37
|
+
* @returns Array of L6Warning for oversized workflows
|
|
38
|
+
*/
|
|
39
|
+
export function checkWorkflowSize(context) {
|
|
40
|
+
const { workflow } = context;
|
|
41
|
+
const warnings = [];
|
|
42
|
+
// Guard: Ensure workflow.nodes exists
|
|
43
|
+
if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
|
|
44
|
+
return warnings;
|
|
45
|
+
}
|
|
46
|
+
const nodeCount = workflow.nodes.length;
|
|
47
|
+
// Only report if above critical threshold (100+)
|
|
48
|
+
// Per assignment: trigger at SIZE_THRESHOLDS.critical
|
|
49
|
+
if (nodeCount >= SIZE_THRESHOLDS.critical) {
|
|
50
|
+
const code = 'OVERSIZED_WORKFLOW';
|
|
51
|
+
warnings.push({
|
|
52
|
+
code: 'OVERSIZED_WORKFLOW',
|
|
53
|
+
message: `Workflow has ${nodeCount} nodes (>${SIZE_THRESHOLDS.critical}). Consider splitting into sub-workflows for better maintainability.`,
|
|
54
|
+
node_name: '__workflow__',
|
|
55
|
+
severity: getL6Severity(code),
|
|
56
|
+
blocks_certification: blocksCertification(code),
|
|
57
|
+
details: {
|
|
58
|
+
node_count: nodeCount,
|
|
59
|
+
threshold: SIZE_THRESHOLDS.critical,
|
|
60
|
+
warning_threshold: SIZE_THRESHOLDS.warning,
|
|
61
|
+
},
|
|
62
|
+
suggested_fix: {
|
|
63
|
+
id: `fix-oversized-workflow-${Date.now()}`,
|
|
64
|
+
fix_type: 'split_workflow',
|
|
65
|
+
confidence: 0.5,
|
|
66
|
+
auto_applicable: false,
|
|
67
|
+
description: 'Split workflow into smaller sub-workflows using Execute Workflow node',
|
|
68
|
+
target_node: '__workflow__',
|
|
69
|
+
patch: {},
|
|
70
|
+
context: {
|
|
71
|
+
current_node_count: nodeCount,
|
|
72
|
+
recommendation: 'Consider grouping related nodes into sub-workflows',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else if (nodeCount >= SIZE_THRESHOLDS.warning) {
|
|
78
|
+
// Warn at 50+ nodes but less critical
|
|
79
|
+
const code = 'OVERSIZED_WORKFLOW';
|
|
80
|
+
warnings.push({
|
|
81
|
+
code: 'OVERSIZED_WORKFLOW',
|
|
82
|
+
message: `Workflow has ${nodeCount} nodes (>${SIZE_THRESHOLDS.warning}). May impact performance.`,
|
|
83
|
+
node_name: '__workflow__',
|
|
84
|
+
severity: getL6Severity(code),
|
|
85
|
+
blocks_certification: blocksCertification(code),
|
|
86
|
+
details: {
|
|
87
|
+
node_count: nodeCount,
|
|
88
|
+
threshold: SIZE_THRESHOLDS.warning,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return warnings;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Check for excessive retry configurations (>10 retries)
|
|
96
|
+
*
|
|
97
|
+
* Nodes with too many retries can cause:
|
|
98
|
+
* - Long delays during failure scenarios
|
|
99
|
+
* - Resource exhaustion
|
|
100
|
+
* - Poor user experience
|
|
101
|
+
*
|
|
102
|
+
* @param context - L6 validation context
|
|
103
|
+
* @returns Array of L6Warning for nodes with excessive retries
|
|
104
|
+
*/
|
|
105
|
+
export function checkExcessiveRetries(context) {
|
|
106
|
+
const { workflow } = context;
|
|
107
|
+
const warnings = [];
|
|
108
|
+
// Guard: Ensure workflow.nodes exists
|
|
109
|
+
if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
|
|
110
|
+
return warnings;
|
|
111
|
+
}
|
|
112
|
+
for (const node of workflow.nodes) {
|
|
113
|
+
// Check if node has retry configured
|
|
114
|
+
// n8n uses retryOnFail boolean and maxTries number
|
|
115
|
+
const retryOnFail = node.retryOnFail;
|
|
116
|
+
const maxTries = node.maxTries || 3;
|
|
117
|
+
const waitBetweenTries = node.waitBetweenTries || 1000;
|
|
118
|
+
// Only check if retry is actually enabled
|
|
119
|
+
if (!retryOnFail) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (maxTries > MAX_REASONABLE_RETRIES) {
|
|
123
|
+
const maxWaitSeconds = (maxTries * waitBetweenTries) / 1000;
|
|
124
|
+
const code = 'EXCESSIVE_RETRY';
|
|
125
|
+
warnings.push({
|
|
126
|
+
code: 'EXCESSIVE_RETRY',
|
|
127
|
+
message: `Node "${node.name}" has ${maxTries} retries (>${MAX_REASONABLE_RETRIES}). Maximum wait time: ${maxWaitSeconds}s.`,
|
|
128
|
+
node_name: node.name,
|
|
129
|
+
node_type: node.type,
|
|
130
|
+
severity: getL6Severity(code),
|
|
131
|
+
blocks_certification: blocksCertification(code),
|
|
132
|
+
details: {
|
|
133
|
+
max_tries: maxTries,
|
|
134
|
+
threshold: MAX_REASONABLE_RETRIES,
|
|
135
|
+
wait_between_tries_ms: waitBetweenTries,
|
|
136
|
+
max_wait_seconds: maxWaitSeconds,
|
|
137
|
+
},
|
|
138
|
+
suggested_fix: {
|
|
139
|
+
id: `fix-excessive-retry-${node.name}-${Date.now()}`,
|
|
140
|
+
fix_type: 'reduce_retries',
|
|
141
|
+
confidence: 0.8,
|
|
142
|
+
auto_applicable: true,
|
|
143
|
+
description: `Reduce maxTries from ${maxTries} to ${MAX_REASONABLE_RETRIES} or less`,
|
|
144
|
+
target_node: node.name,
|
|
145
|
+
patch: {
|
|
146
|
+
node_settings: {
|
|
147
|
+
maxTries: MAX_REASONABLE_RETRIES,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
context: {
|
|
151
|
+
current_max_tries: maxTries,
|
|
152
|
+
recommended_max_tries: MAX_REASONABLE_RETRIES,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return warnings;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Run all performance checks
|
|
162
|
+
*
|
|
163
|
+
* @param context - L6 validation context
|
|
164
|
+
* @returns Object containing errors and warnings
|
|
165
|
+
*/
|
|
166
|
+
export async function checkPerformance(context) {
|
|
167
|
+
const startTime = performance.now();
|
|
168
|
+
// Run checks in parallel
|
|
169
|
+
const [oversizedWarnings, excessiveRetryWarnings,] = await Promise.all([
|
|
170
|
+
Promise.resolve(checkWorkflowSize(context)),
|
|
171
|
+
Promise.resolve(checkExcessiveRetries(context)),
|
|
172
|
+
]);
|
|
173
|
+
const duration = performance.now() - startTime;
|
|
174
|
+
return {
|
|
175
|
+
errors: [], // Performance checks are warnings only
|
|
176
|
+
warnings: [
|
|
177
|
+
...oversizedWarnings,
|
|
178
|
+
...excessiveRetryWarnings,
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=performance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/validation/l6-checks/performance.ts"],"names":[],"mappings":"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"}
|