mirror of
https://github.com/czlonkowski/n8n-mcp.git
synced 2026-03-24 11:23:08 +00:00
fix: resolve remaining AI validation integration test failures
- Simplified Calculator and Think tool validators (no toolDescription required - built-in descriptions) - Fixed trigger counting to exclude respondToWebhook from trigger detection - Fixed streaming error filters to use correct error code access pattern (details.code || code) This resolves 9 remaining integration test failures from Phase 2 AI validation implementation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -409,48 +409,16 @@ export function validateMCPClientTool(node: WorkflowNode): ValidationIssue[] {
|
|||||||
export function validateCalculatorTool(node: WorkflowNode): ValidationIssue[] {
|
export function validateCalculatorTool(node: WorkflowNode): ValidationIssue[] {
|
||||||
const issues: ValidationIssue[] = [];
|
const issues: ValidationIssue[] = [];
|
||||||
|
|
||||||
// Check toolDescription (REQUIRED)
|
// Calculator Tool has a built-in description and is self-explanatory
|
||||||
if (!node.parameters.toolDescription) {
|
// toolDescription is optional - no validation needed
|
||||||
issues.push({
|
|
||||||
severity: 'error',
|
|
||||||
nodeId: node.id,
|
|
||||||
nodeName: node.name,
|
|
||||||
message: `Calculator Tool "${node.name}" has no toolDescription. Add one to help the LLM know when to use this tool.`,
|
|
||||||
code: 'MISSING_TOOL_DESCRIPTION'
|
|
||||||
});
|
|
||||||
} else if (node.parameters.toolDescription.trim().length < MIN_DESCRIPTION_LENGTH_SHORT) {
|
|
||||||
issues.push({
|
|
||||||
severity: 'info',
|
|
||||||
nodeId: node.id,
|
|
||||||
nodeName: node.name,
|
|
||||||
message: `Calculator Tool "${node.name}" has a very short toolDescription (minimum ${MIN_DESCRIPTION_LENGTH_SHORT} characters). Consider being more specific about when to use it.`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return issues;
|
return issues;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateThinkTool(node: WorkflowNode): ValidationIssue[] {
|
export function validateThinkTool(node: WorkflowNode): ValidationIssue[] {
|
||||||
const issues: ValidationIssue[] = [];
|
const issues: ValidationIssue[] = [];
|
||||||
|
|
||||||
// Check toolDescription (REQUIRED)
|
// Think Tool has a built-in description and is self-explanatory
|
||||||
if (!node.parameters.toolDescription) {
|
// toolDescription is optional - no validation needed
|
||||||
issues.push({
|
|
||||||
severity: 'error',
|
|
||||||
nodeId: node.id,
|
|
||||||
nodeName: node.name,
|
|
||||||
message: `Think Tool "${node.name}" has no toolDescription. Add one to help the LLM know when to use thinking.`,
|
|
||||||
code: 'MISSING_TOOL_DESCRIPTION'
|
|
||||||
});
|
|
||||||
} else if (node.parameters.toolDescription.trim().length < MIN_DESCRIPTION_LENGTH_MEDIUM) {
|
|
||||||
issues.push({
|
|
||||||
severity: 'info',
|
|
||||||
nodeId: node.id,
|
|
||||||
nodeName: node.name,
|
|
||||||
message: `Think Tool "${node.name}" has a very short toolDescription (minimum ${MIN_DESCRIPTION_LENGTH_MEDIUM} characters). Explain when the agent should use thinking vs. action.`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return issues;
|
return issues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -327,8 +327,9 @@ export class WorkflowValidator {
|
|||||||
// Count trigger nodes - normalize type names first
|
// Count trigger nodes - normalize type names first
|
||||||
const triggerNodes = workflow.nodes.filter(n => {
|
const triggerNodes = workflow.nodes.filter(n => {
|
||||||
const normalizedType = NodeTypeNormalizer.normalizeToFullForm(n.type);
|
const normalizedType = NodeTypeNormalizer.normalizeToFullForm(n.type);
|
||||||
return normalizedType.toLowerCase().includes('trigger') ||
|
const lowerType = normalizedType.toLowerCase();
|
||||||
normalizedType.toLowerCase().includes('webhook') ||
|
return lowerType.includes('trigger') ||
|
||||||
|
(lowerType.includes('webhook') && !lowerType.includes('respond')) ||
|
||||||
normalizedType === 'nodes-base.start' ||
|
normalizedType === 'nodes-base.start' ||
|
||||||
normalizedType === 'nodes-base.manualTrigger' ||
|
normalizedType === 'nodes-base.manualTrigger' ||
|
||||||
normalizedType === 'nodes-base.formTrigger';
|
normalizedType === 'nodes-base.formTrigger';
|
||||||
|
|||||||
@@ -245,10 +245,11 @@ describe('Integration: AI Agent Validation', () => {
|
|||||||
expect(data.valid).toBe(false);
|
expect(data.valid).toBe(false);
|
||||||
expect(data.errors).toBeDefined();
|
expect(data.errors).toBeDefined();
|
||||||
|
|
||||||
const streamingErrors = data.errors!.filter(e =>
|
const streamingErrors = data.errors!.filter(e => {
|
||||||
e.code === 'STREAMING_WITH_MAIN_OUTPUT' ||
|
const code = e.details?.code || e.code;
|
||||||
e.code === 'STREAMING_AGENT_HAS_OUTPUT'
|
return code === 'STREAMING_WITH_MAIN_OUTPUT' ||
|
||||||
);
|
code === 'STREAMING_AGENT_HAS_OUTPUT';
|
||||||
|
});
|
||||||
expect(streamingErrors.length).toBeGreaterThan(0);
|
expect(streamingErrors.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -308,10 +308,11 @@ describe('Integration: Chat Trigger Validation', () => {
|
|||||||
expect(data.errors).toBeDefined();
|
expect(data.errors).toBeDefined();
|
||||||
|
|
||||||
// Should detect streaming agent has output
|
// Should detect streaming agent has output
|
||||||
const streamingErrors = data.errors!.filter(e =>
|
const streamingErrors = data.errors!.filter(e => {
|
||||||
e.code === 'STREAMING_AGENT_HAS_OUTPUT' ||
|
const code = e.details?.code || e.code;
|
||||||
e.message.toLowerCase().includes('streaming')
|
return code === 'STREAMING_AGENT_HAS_OUTPUT' ||
|
||||||
);
|
e.message.toLowerCase().includes('streaming');
|
||||||
|
});
|
||||||
expect(streamingErrors.length).toBeGreaterThan(0);
|
expect(streamingErrors.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -219,10 +219,11 @@ describe('Integration: End-to-End AI Workflow Validation', () => {
|
|||||||
expect(errorCodes).toContain('MISSING_CODE'); // Code Tool
|
expect(errorCodes).toContain('MISSING_CODE'); // Code Tool
|
||||||
|
|
||||||
// Should also have streaming error
|
// Should also have streaming error
|
||||||
const streamingErrors = validationData.errors!.filter(e =>
|
const streamingErrors = validationData.errors!.filter(e => {
|
||||||
e.code === 'STREAMING_WITH_MAIN_OUTPUT' ||
|
const code = e.details?.code || e.code;
|
||||||
e.code === 'STREAMING_AGENT_HAS_OUTPUT'
|
return code === 'STREAMING_WITH_MAIN_OUTPUT' ||
|
||||||
);
|
code === 'STREAMING_AGENT_HAS_OUTPUT';
|
||||||
|
});
|
||||||
expect(streamingErrors.length).toBeGreaterThan(0);
|
expect(streamingErrors.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
// Verify error messages are actionable
|
// Verify error messages are actionable
|
||||||
|
|||||||
Reference in New Issue
Block a user