fix(p0): remove incorrect node type normalization before n8n API calls

## Bug Description
handleCreateWorkflow and handleUpdateFullWorkflow were incorrectly
normalizing node types from FULL form (n8n-nodes-base.webhook) to
SHORT form (nodes-base.webhook) before validation and API calls.

This caused 100% failure rate for workflow creation because:
- n8n API requires FULL form (n8n-nodes-base.*)
- Database stores SHORT form (nodes-base.*)
- NodeTypeNormalizer converts TO SHORT form (for database)
- But was being used BEFORE API calls (incorrect)

## Root Cause
NodeTypeNormalizer was designed for database lookups but was
incorrectly applied to API operations. The method name
`normalizeToFullForm()` is misleading - it actually normalizes
TO SHORT form.

## Changes
1. handlers-n8n-manager.ts:
   - Removed NodeTypeNormalizer.normalizeWorkflowNodeTypes() from
     handleCreateWorkflow (line 288)
   - Removed normalization from handleUpdateFullWorkflow (line 544-557)
   - Added proactive SHORT form detection with helpful errors
   - Added comments explaining n8n API expects FULL form

2. node-type-normalizer.ts:
   - Added prominent WARNING about not using before API calls
   - Added examples showing CORRECT vs INCORRECT usage
   - Clarified this is FOR DATABASE OPERATIONS ONLY

3. handlers-n8n-manager.test.ts:
   - Fixed test to expect FULL form (not SHORT) sent to API
   - Removed incorrect expectedNormalizedInput assertion

4. NEW: workflow-creation-node-type-format.test.ts:
   - 7 integration tests with real validation (unmocked)
   - Tests FULL form acceptance, SHORT form rejection
   - Tests real-world workflows (webhook, schedule trigger)
   - Regression test to prevent bug reintroduction

## Verification
Before fix:
 Manual Trigger → Set: FAILED
 Webhook → HTTP Request: FAILED
Failure rate: 100%

After fix:
 Manual Trigger → Set: SUCCESS (ID: kTAaDZwdpzj8gqzM)
 Webhook → HTTP Request: SUCCESS (ID: aPtQUb54uuHIqX52)
 All 39 tests passing (32 unit + 7 integration)
Success rate: 100%

## Impact
- Fixes: Complete blocking bug preventing all workflow creation
- Risk: Zero (removing buggy behavior)
- Breaking: None (external API unchanged)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-10-03 11:43:49 +02:00
parent 5bf1bc46e9
commit d875ac1e0c
7 changed files with 578 additions and 162 deletions

View File

@@ -1,27 +1,44 @@
/**
* Universal Node Type Normalizer
* Universal Node Type Normalizer - FOR DATABASE OPERATIONS ONLY
*
* Converts ANY node type variation to the canonical SHORT form used by the database.
* This fixes the critical issue where AI agents or external sources may produce
* full-form node types (e.g., "n8n-nodes-base.webhook") which need to be normalized
* to match the database storage format (e.g., "nodes-base.webhook").
* ⚠️ WARNING: Do NOT use before n8n API calls!
*
* This class converts node types to SHORT form (database format).
* The n8n API requires FULL form (n8n-nodes-base.*).
*
* **Use this ONLY when:**
* - Querying the node database
* - Searching for node information
* - Looking up node metadata
*
* **Do NOT use before:**
* - Creating workflows (n8n_create_workflow)
* - Updating workflows (n8n_update_workflow)
* - Any n8n API calls
*
* **IMPORTANT:** The n8n-mcp database stores nodes in SHORT form:
* - n8n-nodes-base → nodes-base
* - @n8n/n8n-nodes-langchain → nodes-langchain
*
* Handles:
* - Full form → Short form (n8n-nodes-base.X → nodes-base.X)
* - Already short form → Unchanged
* - LangChain nodes → Proper short prefix
* But the n8n API requires FULL form:
* - nodes-base → n8n-nodes-base
* - nodes-langchain → @n8n/n8n-nodes-langchain
*
* @example
* NodeTypeNormalizer.normalizeToFullForm('n8n-nodes-base.webhook')
* @example Database Lookup (CORRECT usage)
* const dbType = NodeTypeNormalizer.normalizeToFullForm('n8n-nodes-base.webhook')
* // → 'nodes-base.webhook'
* const node = await repository.getNode(dbType)
*
* @example
* NodeTypeNormalizer.normalizeToFullForm('nodes-base.webhook')
* // → 'nodes-base.webhook' (unchanged)
* @example API Call (INCORRECT - Do NOT do this!)
* const workflow = { nodes: [{ type: 'n8n-nodes-base.webhook' }] }
* const normalized = NodeTypeNormalizer.normalizeWorkflowNodeTypes(workflow)
* // ❌ WRONG! normalized has SHORT form, API needs FULL form
* await client.createWorkflow(normalized) // FAILS!
*
* @example API Call (CORRECT)
* const workflow = { nodes: [{ type: 'n8n-nodes-base.webhook' }] }
* // ✅ Send as-is to API (FULL form required)
* await client.createWorkflow(workflow) // WORKS!
*/
export interface NodeTypeNormalizationResult {