fix: resolve node type normalization bug blocking all AI validation (HIGH-01, HIGH-04, HIGH-08)

CRITICAL BUG FIX:
NodeTypeNormalizer.normalizeToFullForm() converts TO SHORT form (nodes-langchain.*),
but all validation code compared against FULL form (@n8n/n8n-nodes-langchain.*).
This caused ALL AI validation to be silently skipped.

Impact:
- Missing language model detection: NEVER triggered
- AI tool connection detection: NEVER triggered
- Streaming mode validation: NEVER triggered
- AI tool sub-node validation: NEVER triggered

ROOT CAUSE:
Line 348 in ai-node-validator.ts (and 19 other locations):
  if (normalizedType === '@n8n/n8n-nodes-langchain.agent') // FULL form
But normalizedType is 'nodes-langchain.agent' (SHORT form)
Result: Comparison always FALSE, validation never runs

FIXES:
1. ai-node-validator.ts (7 locations):
   - Lines 551, 557, 563: validateAISpecificNodes comparisons
   - Line 348: checkIfStreamingTarget comparison
   - Lines 417, 444: validateChatTrigger comparisons
   - Lines 589-591: hasAINodes array
   - Lines 606-608, 612: getAINodeCategory comparisons

2. ai-tool-validators.ts (14 locations):
   - Lines 980-991: AI_TOOL_VALIDATORS keys (13 validators)
   - Lines 1015-1037: validateAIToolSubNode switch cases (13 cases)

3. ENHANCED streaming validation:
   - Added validation for AI Agent's own streamResponse setting
   - Previously only checked streaming FROM Chat Trigger
   - Now validates BOTH scenarios (lines 259-276)

VERIFICATION:
- All 25 AI validator unit tests:  PASS
- Debug test (missing LM):  PASS
- Debug test (AI tools):  PASS
- Debug test (streaming):  PASS

Resolves:
- HIGH-01: Missing language model detection (was never running)
- HIGH-04: AI tool connection detection (was never running)
- HIGH-08: Streaming mode validation (was never running + incomplete)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-10-06 23:36:56 +02:00
parent ccbe04f007
commit 92eb4ef34f
4 changed files with 233 additions and 39 deletions

View File

@@ -977,18 +977,18 @@ export function validateWolframAlphaTool(node: WorkflowNode): ValidationIssue[]
* Helper: Map node types to validator functions
*/
export const AI_TOOL_VALIDATORS = {
'@n8n/n8n-nodes-langchain.toolHttpRequest': validateHTTPRequestTool,
'@n8n/n8n-nodes-langchain.toolCode': validateCodeTool,
'@n8n/n8n-nodes-langchain.toolVectorStore': validateVectorStoreTool,
'@n8n/n8n-nodes-langchain.toolWorkflow': validateWorkflowTool,
'@n8n/n8n-nodes-langchain.agentTool': validateAIAgentTool,
'@n8n/n8n-nodes-langchain.mcpClientTool': validateMCPClientTool,
'@n8n/n8n-nodes-langchain.toolCalculator': validateCalculatorTool,
'@n8n/n8n-nodes-langchain.toolThink': validateThinkTool,
'@n8n/n8n-nodes-langchain.toolSerpApi': validateSerpApiTool,
'@n8n/n8n-nodes-langchain.toolWikipedia': validateWikipediaTool,
'@n8n/n8n-nodes-langchain.toolSearXng': validateSearXngTool,
'@n8n/n8n-nodes-langchain.toolWolframAlpha': validateWolframAlphaTool,
'nodes-langchain.toolHttpRequest': validateHTTPRequestTool,
'nodes-langchain.toolCode': validateCodeTool,
'nodes-langchain.toolVectorStore': validateVectorStoreTool,
'nodes-langchain.toolWorkflow': validateWorkflowTool,
'nodes-langchain.agentTool': validateAIAgentTool,
'nodes-langchain.mcpClientTool': validateMCPClientTool,
'nodes-langchain.toolCalculator': validateCalculatorTool,
'nodes-langchain.toolThink': validateThinkTool,
'nodes-langchain.toolSerpApi': validateSerpApiTool,
'nodes-langchain.toolWikipedia': validateWikipediaTool,
'nodes-langchain.toolSearXng': validateSearXngTool,
'nodes-langchain.toolWolframAlpha': validateWolframAlphaTool,
} as const;
/**
@@ -1012,29 +1012,29 @@ export function validateAIToolSubNode(
// Route to appropriate validator based on node type
switch (normalized) {
case '@n8n/n8n-nodes-langchain.toolHttpRequest':
case 'nodes-langchain.toolHttpRequest':
return validateHTTPRequestTool(node);
case '@n8n/n8n-nodes-langchain.toolCode':
case 'nodes-langchain.toolCode':
return validateCodeTool(node);
case '@n8n/n8n-nodes-langchain.toolVectorStore':
case 'nodes-langchain.toolVectorStore':
return validateVectorStoreTool(node, reverseConnections, workflow);
case '@n8n/n8n-nodes-langchain.toolWorkflow':
case 'nodes-langchain.toolWorkflow':
return validateWorkflowTool(node);
case '@n8n/n8n-nodes-langchain.agentTool':
case 'nodes-langchain.agentTool':
return validateAIAgentTool(node, reverseConnections);
case '@n8n/n8n-nodes-langchain.mcpClientTool':
case 'nodes-langchain.mcpClientTool':
return validateMCPClientTool(node);
case '@n8n/n8n-nodes-langchain.toolCalculator':
case 'nodes-langchain.toolCalculator':
return validateCalculatorTool(node);
case '@n8n/n8n-nodes-langchain.toolThink':
case 'nodes-langchain.toolThink':
return validateThinkTool(node);
case '@n8n/n8n-nodes-langchain.toolSerpApi':
case 'nodes-langchain.toolSerpApi':
return validateSerpApiTool(node);
case '@n8n/n8n-nodes-langchain.toolWikipedia':
case 'nodes-langchain.toolWikipedia':
return validateWikipediaTool(node);
case '@n8n/n8n-nodes-langchain.toolSearXng':
case 'nodes-langchain.toolSearXng':
return validateSearXngTool(node);
case '@n8n/n8n-nodes-langchain.toolWolframAlpha':
case 'nodes-langchain.toolWolframAlpha':
return validateWolframAlphaTool(node);
default:
return [];